diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 195c1a53c..ad6b4fd45 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -@arun2k17 @corinagum @halbondmsft @pradeepananth @ryanbliss @siduppal @Stevenic +@pradeepananth @ryanbliss @siduppal @huntj88 diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md index 1fbf1646a..48e216574 100644 --- a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md @@ -1,9 +1,11 @@ ## Linked issues + > What issue(s) does this Pull Request address? Issues: # (issue number) ## Details + #### PR type: - [ ] Bug fix @@ -12,25 +14,26 @@ Issues: # (issue number) - [ ] Samples or Test coverage #### Change details + > Describe your changes, with screenshots and code snippets as appropriate **code snippets**: **screenshots**: +## Checklist -## Checklist + - [ ] I have checked for/fixed spelling, linting, and other errors - [ ] I have commented my code for clarity - [ ] I have made corresponding changes to the documentation (we use [TypeDoc](https://typedoc.org/) to document our code) - [ ] My changes generate no new warnings - [ ] I have added tests that validates my changes, and provides sufficient test coverage. I have tested with: - - [ ] Local testing - - [ ] E2E testing in Teams + - [ ] Local testing + - [ ] E2E testing in Teams - [ ] New and existing unit tests pass locally with my changes ### Additional information > Feel free to add other relevant information below - diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 96bb45198..bea2e8b3e 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,21 +1,21 @@ version: 2 updates: - - package-ecosystem: "npm" - # Only specify the root so dependabot will update all manifests once per package - # See https://github.com/dependabot/dependabot-core/issues/5226#issuecomment-1179434437 - directory: "/" - schedule: - interval: "weekly" - day: "monday" - # Ignore the following packages because - # 1. Semver for these packages is not always followed - # 1. These packages MUST be updated all at the same time (same PR) - ignore: - - "fluid-framework", - - "@fluidframework/test-client-utils" - - "@fluidframework/test-utils" - - "@fluidframework/test-runtime-utils" - - "@fluidframework/azure-client", - - "@microsoft/teams-js" - # Updates both the package-lock and package.json, not just package-lock - versioning-strategy: increase + - package-ecosystem: "npm" + # Only specify the root so dependabot will update all manifests once per package + # See https://github.com/dependabot/dependabot-core/issues/5226#issuecomment-1179434437 + directory: "/" + schedule: + interval: "weekly" + day: "monday" + # Ignore the following packages because + # 1. Semver for these packages is not always followed + # 1. These packages MUST be updated all at the same time (same PR) + ignore: + - dependency-name: "fluid-framework" + - dependency-name: "@fluidframework/test-client-utils" + - dependency-name: "@fluidframework/test-utils" + - dependency-name: "@fluidframework/test-runtime-utils" + - dependency-name: "@fluidframework/azure-client" + - dependency-name: "@microsoft/teams-js" + # Updates both the package-lock and package.json, not just package-lock + versioning-strategy: increase diff --git a/.github/workflows/checkFormatting.sh b/.github/workflows/checkFormatting.sh new file mode 100644 index 000000000..d2cdbc949 --- /dev/null +++ b/.github/workflows/checkFormatting.sh @@ -0,0 +1,15 @@ +#!/bin/bash +cd ../.. +npm run doctor +diff=`git diff` +if [ -z "$diff" ] +then + echo "everything formatted" + exit 0 +else + echo "" # empty line + echo "" # empty line + echo "FORMATTING NEEDED" + echo "Please run 'npm run doctor'" + exit 1 +fi diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml deleted file mode 100644 index fdaf3c869..000000000 --- a/.github/workflows/codeql.yaml +++ /dev/null @@ -1,75 +0,0 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# -name: 'CodeQL' - -on: - push: - branches: ['main', main*] - pull_request: - # The branches below must be a subset of the branches above - branches: ['main'] - schedule: - - cron: '0 2 * * 6' - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: ['javascript'] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] - # Use only 'java' to analyze code written in Java, Kotlin or both - # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both - # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support - - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - - # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - # queries: security-extended,security-and-quality - - # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v2 - - # ℹ️ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - - # If the Autobuild fails above, remove it and uncomment the following three lines. - # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. - - # - run: | - # echo "Run, Build Application using script" - # ./location_of_script_within_repo/buildscript.sh - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 - with: - category: '/language:${{matrix.language}}' diff --git a/.github/workflows/live-share-build-samples.yaml b/.github/workflows/live-share-build-samples.yaml index ea137d529..dfacc5cd2 100644 --- a/.github/workflows/live-share-build-samples.yaml +++ b/.github/workflows/live-share-build-samples.yaml @@ -1,36 +1,39 @@ name: Build Live Share SDK samples on: - push: - branches: [ main ] - pull_request: - branches: [ main ] + push: + branches: [main, mainv2] + pull_request: + branches: [main, mainv2, "user/**", "copilot/**"] + workflow_dispatch: jobs: - build: - - runs-on: ubuntu-latest - - strategy: - matrix: - node-version: [18.x] - - steps: - - uses: actions/checkout@v3 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 - with: - node-version: ${{ matrix.node-version }} - - run: npm install - - run: npm install jest - working-directory: samples/javascript/02.react-video - - - name: "build packages and samples" - run: npm run build - - # TODO: get scenario_test.sh working - - # - name: "test 02.react-video sample" - # shell: "bash" - # run: sh ../../../.github/workflows/scenario_test.sh - # working-directory: samples/javascript/02.react-video + build: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [22.x, 24.x] + + steps: + - uses: actions/checkout@v4 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: "npm" + - run: npm --loglevel verbose ci --ignore-scripts + timeout-minutes: 20 + + - run: npm install jest + working-directory: samples/javascript/02.react-video + + - name: "build packages and samples" + run: npm run build + + # TODO: get scenario_test.sh working + + # - name: "test 02.react-video sample" + # shell: "bash" + # run: sh ../../../.github/workflows/scenario_test.sh + # working-directory: samples/javascript/02.react-video diff --git a/.github/workflows/live-share-formatting.yaml b/.github/workflows/live-share-formatting.yaml new file mode 100644 index 000000000..0f5a39257 --- /dev/null +++ b/.github/workflows/live-share-formatting.yaml @@ -0,0 +1,31 @@ +name: Check formatting + +on: + push: + branches: [main, mainv2] + pull_request: + branches: [main, mainv2, "user/**", "copilot/**"] + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [22.x, 24.x] + + steps: + - uses: actions/checkout@v4 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: "npm" + + - run: npm --loglevel verbose ci --ignore-scripts + timeout-minutes: 20 + + - name: "check formatting" + run: "bash checkFormatting.sh" + working-directory: .github/workflows diff --git a/.github/workflows/live-share-test-packages.yaml b/.github/workflows/live-share-test-packages.yaml index a95b7a569..036761fcb 100644 --- a/.github/workflows/live-share-test-packages.yaml +++ b/.github/workflows/live-share-test-packages.yaml @@ -1,41 +1,40 @@ name: Test Live Share SDK packages on: - push: - branches: [ main ] - pull_request: - branches: [ main ] + push: + branches: [main, mainv2] + pull_request: + branches: [main, mainv2, "user/**", "copilot/**"] + workflow_dispatch: jobs: - build: - - runs-on: ubuntu-latest - - strategy: - matrix: - node-version: [18.x] - - steps: - - uses: actions/checkout@v3 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 - with: - node-version: ${{ matrix.node-version }} - - run: npm install - - run: npm run build:packages - - - name: "test live-share" - run: npm run test - working-directory: packages/live-share - - - name: "test live-share-canvas" - run: npm run test - working-directory: packages/live-share-canvas - - - name: "test live-share-media" - run: npm run test - working-directory: packages/live-share-media - - - name: "test live-share-turbo" - run: npm run test - working-directory: packages/live-share-turbo + build: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [22.x, 24.x] + + steps: + - uses: actions/checkout@v4 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: "npm" + - run: npm --loglevel verbose ci --ignore-scripts + timeout-minutes: 20 + + - run: npm run prepare # will trigger a build of all packages + + - name: "test live-share" + run: npm run test + working-directory: packages/live-share + + - name: "test live-share-canvas" + run: npm run test + working-directory: packages/live-share-canvas + + - name: "test live-share-media" + run: npm run test + working-directory: packages/live-share-media diff --git a/.github/workflows/live-share-test-usage.yaml b/.github/workflows/live-share-test-usage.yaml new file mode 100644 index 000000000..bad840940 --- /dev/null +++ b/.github/workflows/live-share-test-usage.yaml @@ -0,0 +1,41 @@ +name: Test Usage of Live Share SDK packages in different JS environments + +on: + push: + branches: [main, mainv2] + pull_request: + branches: [main, mainv2, "user/**", "copilot/**"] + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [22.x, 24.x] + + steps: + - uses: actions/checkout@v4 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: "npm" + - run: npm --loglevel verbose ci --ignore-scripts + timeout-minutes: 20 + + - run: npm run prepare # will trigger a build of all packages + + - name: "test live-share with esm app" + run: npm run test + working-directory: internal/usage-test/esm-test + + - uses: pnpm/action-setup@v4 + name: Install pnpm for next step + with: + version: 9 + run_install: false + - name: "test live-share with pnpm typescript esm app" + run: pnpm run test + working-directory: internal/usage-test/pnpm-test diff --git a/.gitignore b/.gitignore index 505b7ac60..5eaeeb43b 100644 --- a/.gitignore +++ b/.gitignore @@ -365,5 +365,7 @@ docs/assets/main.js # Testing files coverage/ +nyc/ .nyc_output/ -build-data.json \ No newline at end of file +build-data.json +tsconfig.tsbuildinfo diff --git a/.npmignore b/.npmignore index f2941a1b0..5e32b6ccc 100644 --- a/.npmignore +++ b/.npmignore @@ -2,4 +2,9 @@ node_modules .vscode package-lock.json tinylicious.log -src/test/ \ No newline at end of file +src/test/ +bin/test/ +nyc/ +.mocharc.cjs +.nycrc.json +tsconfig.test.json diff --git a/.sdl/CredScanSuppressions.json b/.sdl/CredScanSuppressions.json index f045498d8..0e52eb402 100644 --- a/.sdl/CredScanSuppressions.json +++ b/.sdl/CredScanSuppressions.json @@ -1,5 +1,4 @@ { - "tool": "Credential Scanner", - "suppressions": [ - ] -} \ No newline at end of file + "tool": "Credential Scanner", + "suppressions": [] +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 35682e1ce..c9a076270 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,22 +2,22 @@ ## Contributing bug fixes and features -Microsoft Teams is currently accepting contributions in the form of bug fixes and new +Microsoft Teams is currently accepting contributions in the form of bug fixes and new features. Any submission must have an issue tracking it in the issue tracker that has - been approved by the Teams Collaboration team. Your pull request should include a link to - the bug that you are fixing. If you've submitted a PR for a bug, please post a - comment in the bug to avoid duplication of effort. +been approved by the Teams Collaboration team. Your pull request should include a link to +the bug that you are fixing. If you've submitted a PR for a bug, please post a +comment in the bug to avoid duplication of effort. ## Legal -If your contribution is more than 15 lines of code, you will need to complete a Contributor +If your contribution is more than 15 lines of code, you will need to complete a Contributor License Agreement (CLA). Briefly, this agreement testifies that you are granting us permission - to use the submitted change according to the terms of the project's license, and that the work - being submitted is under appropriate copyright. +to use the submitted change according to the terms of the project's license, and that the work +being submitted is under appropriate copyright. -Please submit a Contributor License Agreement (CLA) before submitting a pull request. -You may visit https://cla.azure.com to sign digitally. Alternatively, download the +Please submit a Contributor License Agreement (CLA) before submitting a pull request. +You may visit https://cla.azure.com to sign digitally. Alternatively, download the agreement ([Microsoft Contribution License Agreement.docx](https://www.codeplex.com/Download?ProjectName=typescript&DownloadId=822190) or - [Microsoft Contribution License Agreement.pdf](https://www.codeplex.com/Download?ProjectName=typescript&DownloadId=921298)), sign, scan, - and email it back to . Be sure to include your github user name along with the agreement. Once we have received the - signed CLA, we'll review the request. \ No newline at end of file +[Microsoft Contribution License Agreement.pdf](https://www.codeplex.com/Download?ProjectName=typescript&DownloadId=921298)), sign, scan, +and email it back to . Be sure to include your github user name along with the agreement. Once we have received the +signed CLA, we'll review the request. diff --git a/MAINTENENCE.md b/MAINTENENCE.md index 7441b0a73..36b13d5e1 100644 --- a/MAINTENENCE.md +++ b/MAINTENENCE.md @@ -1,12 +1,12 @@ -# Maintanence +# Maintanence > Quick notes & guidelines on how to keep the repo neat & tidy ## Package updates -Dependabot is set up to assist with [package-lock updates](.github/dependabot.yml). +Dependabot is set up to assist with [package-lock updates](.github/dependabot.yml). -- SDK packages will be update weekly on Mondays via a PR from dependabot. +- SDK packages will be update weekly on Mondays via a PR from dependabot. - Samples packages will be updated monthly. - Wherever possible, security updates should be done asap. @@ -23,17 +23,19 @@ Please keep an eye on incoming bugs / requests. When a new issue comes in, we sh 1. Verify we have all information required to reproduce the problem / continue with feature planning (Are all of the questions from the templates answered?) 2. Delete the 'Please review' section of the issue, especially when the issue is filed by a Live Share team member: - ![image](https://user-images.githubusercontent.com/14900841/197058064-bbc56748-09b2-47a1-8c31-6b44a2aa1bc4.png) + ![image](https://user-images.githubusercontent.com/14900841/197058064-bbc56748-09b2-47a1-8c31-6b44a2aa1bc4.png) 3. If needed, bring the newly filed topic up in scrum for discussion: - - Timeline - - Assignee - - Migrate to internal kanban as needed + +- Timeline +- Assignee +- Migrate to internal kanban as needed + 4. Remove the `new submission` tag. This is for a visible indication that the topic is acknowledged by the team. -> Note: if the issue is filed by a Live Share team-member, you can delete `new submission` immediately after submitting. + > Note: if the issue is filed by a Live Share team-member, you can delete `new submission` immediately after submitting. ## Announcements -After a new release, we should verify that a post is made to the Discussions center about the release. +After a new release, we should verify that a post is made to the Discussions center about the release. ## Other considerations diff --git a/README.md b/README.md index 89bd01b83..9a29d4221 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,12 @@ # Live Share SDK -The Live Share SDK builds on the [Fluid Framework](https://fluidframework.com/) to enable the creation of collaborative experiences for Microsoft Teams and Microsoft 365. This package focuses on building collaborative meeting applications for Microsoft Teams using Fluid. The SDK provides a `LiveShareClient` class for connecting to a special Fluid Container associated with each meeting. A collection of Live Share specific Distributed Data Structure (DDS) classes are also provided to simplify building applications for common meeting scenarios like shared media playback. +![Image showing the Live Share SDK used in a Teams meeting to connect two users together via a virtual white board.](assets/readme-banner.png) -To get started, we recommend first familiarizing yourself with the [Fluid Framework](https://fluidframework.com/docs/) and [Live Share overview](https://aka.ms/teamsliveshare). You can then follow our [Quick Start Guide](https://learn.microsoft.com/microsoftteams/platform/apps-in-teams-meetings/teams-live-share-quick-start) to build your first Teams Meeting App that uses Live Share. +The Live Share SDK enables building collaborative applications for Microsoft Teams. The SDK provides a `LiveShareClient` class for connecting to a collaborative session associated with each meeting. It provides a mixture of turn-key collaborative scenarios like media synchronization and inking + cursors, as well as flexible primitive API's to enable synchronizing any state in your application. + +The Live Share SDK builds on [Fluid Framework](https://fluidframework.com/) to enable the creation of collaborative experiences for Microsoft Teams and Microsoft 365. A collection of Live Share specific Distributed Data Structure (DDS) classes are also provided to simplify building applications for common meeting scenarios like shared media playback. + +To get started, you may want to first read our [Live Share docs](https://aka.ms/teamsliveshare) and [Fluid Framework docs](https://fluidframework.com/docs/). You can then follow our [Quick Start Guide](https://learn.microsoft.com/microsoftteams/platform/apps-in-teams-meetings/teams-live-share-quick-start) to build your first Teams Meeting App that uses Live Share. You can find our detailed API reference documentation at [Live Share reference docs](https://docs.microsoft.com/javascript/api/@microsoft/live-share/) and [Live Share Media reference docs](https://docs.microsoft.com/javascript/api/@microsoft/live-share-media/). @@ -13,9 +17,9 @@ You can find our detailed API reference documentation at [Live Share reference d - `LiveShareClient`: Connect to a Fluid container associated with a Microsoft Teams meeting. - `LivePresence`: Track who is using your app during a meeting and associate custom metadata for each user (e.g., camera position). - `LiveState`: Synchronize a JSON-serializable value for maintaining consistent application state across clients. +- `LiveFollowMode` (beta): Easily integrate features to present to all, follow specific users, and suspend/resume following. - `LiveTimer`: Build a collaborative countdown timer. - `LiveEvent`: Send one-time, stateless JSON-serializable values to each user in the session. -- `LiveFollowMode` (beta): Easily integrate features to present to all, follow specific users, and suspend/resume following. [Live Share Canvas](/packages/live-share-canvas/README.md) is an optional extension that allows any app to add a collaborative whiteboard as an app overlay. Key classes include: @@ -31,9 +35,9 @@ You can find our detailed API reference documentation at [Live Share reference d [Fluid Framework](https://fluidframework.com/) also offers some useful collaborative features, each of which is compatible with Live Share, including: -- `SharedMap`: The DDS equivalent to a JavaScript `Map`, which is useful for synchronizing a collection of objects. -- `SharedString`: Synchronize a string text value, useful for building real-time text editors. -- `SharedTree` (alpha): Synchronize a complex tree of intersecting nodes. +- `SharedTree`: Synchronize any object simply by using objects like you normally would in JS/TS. +- `SharedMap` (legacy): The DDS equivalent to a JavaScript `Map`, which is useful for synchronizing a collection of objects. +- `SharedString` (legacy): Synchronize a string text value, useful for building real-time text editors. ## Package Compatibility @@ -41,9 +45,10 @@ The Live Share SDK contains dependencies for [@microsoft/teams-js](https://www.n **It is critical that your app use the package dependencies listed in the table below.** Lookup the version of the `@microsoft/live-share` you're using and set any other dependencies in your package.json file to match: -| @microsoft/live-share | @microsoft/teams-js | fluid-framework | @microsoft/live-share-\* | @fluidframework/azure-client | @microsoft/TeamsFx | @microsoft/TeamsFx-react | -| --------------------- | -------------------- | --------------- | -------------------------- | ---------------------------- | ------------------------------- | ------------------------------- | -| ^1.0.0 | ^2.11.0 | ^1.2.3 | ^1.0.0 | ^1.0.0 | ^2.5.0 | ^2.5.0 | +| @microsoft/live-share | @microsoft/teams-js | fluid-framework | @microsoft/live-share-\* | @fluidframework/azure-client | @microsoft/TeamsFx | @microsoft/TeamsFx-react | +| --------------------- | ------------------- | --------------- | ------------------------ | ---------------------------- | ------------------ | ------------------------ | +| ^2.0.0 | ^2.11.0 | ^2.0.0 | ^2.0.0 | ^2.0.0 | ^2.5.0 | ^2.5.0 | +| ^1.0.0 | ^2.11.0 | ^1.2.3 | ^1.0.0 | ^1.0.0 | ^2.5.0 | ^2.5.0 | ## Installing @@ -108,7 +113,7 @@ yarn add @microsoft/live-share-react There are several ways you can [contribute](./CONTRIBUTING.md) to this project: - [Submit bugs](https://github.com/microsoft/live-share-sdk/issues) and help us verify fixes as they are checked in. - - (Please review [FAQ and Known issues](https://github.com/microsoft/live-share-sdk/issues/8) before filing a new item!) + - (Please review [FAQ and Known issues](https://github.com/microsoft/live-share-sdk/issues/8) before filing a new item!) - Review the source code changes. - Engage with other Live Share developers on [StackOverflow](https://stackoverflow.com/questions/tagged/live-share). - [Contribute bug fixes](./CONTRIBUTING.md). @@ -163,11 +168,11 @@ There are several code samples available to use: | Sample name | Description | Javascript | TypeScript | | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | ----------------------------------------------------- | | Dice Roller | Enable all connected clients to roll a dice and view the result. | [View](./samples/javascript/01.dice-roller/) | [View](./samples/typescript/01.dice-roller/) | -| React Video | Basic example showing how the `LiveMediaSession` class works with HTML5 video. | [View](./samples/javascript/02.react-video/) | | +| React Video | Basic example showing how the `LiveMediaSession` class works with HTML5 video. | [View](./samples/javascript/02.react-video/) | | | Live Canvas demo | Synchronized pens, laser pointers, cursors, and more via Live Share Canvas. | [View](./samples/javascript/03.live-canvas-demo/) | [View](./samples/typescript/03.live-canvas-demo/) | | Live Share React demo | Example of using the Live Share React package. | [View](./samples/javascript/04.live-share-react/) | [View](./samples/typescript/04.live-share-react/) | | React Media Template | Enable all connected clients to watch videos together, build a shared playlist, transfer whom is in control, and annotate over the video. | [View](./samples/javascript/21.react-media-template/) | [View](./samples/typescript/21.react-media-template/) | -| Agile Poker | Enable all connected clients to play an Agile Poker planning activity. | [View](./samples/javascript/22.react-agile-poker/) | | +| Agile Poker | Enable all connected clients to play an Agile Poker planning activity. | [View](./samples/javascript/22.react-agile-poker/) | | ## Reporting Security Issues @@ -177,8 +182,8 @@ Security issues and bugs should be reported privately, via email, to the Microso Copyright (c) Microsoft Corporation. All rights reserved. -Live Share, Live Share media, and Live Share canvas are licensed under a special [Microsoft Live Share SDK license](./LICENSE). +Live Share, Live Share media, Live Share canvas, and Live Share React are licensed under a special [Microsoft Live Share SDK license](./LICENSE). -Live Share Turbo and Live Share React are licensed under a special [Microsoft Live Share SDK - Pre-Release Version license](./packages/live-share-turbo/LICENSE). +Live Share ACS is licensed under a special [Microsoft Live Share SDK - Pre-Release Version license](./packages/live-share-acs/LICENSE). Code samples are licensed separately under [MIT license](./samples/LICENSE). diff --git a/SECURITY.md b/SECURITY.md index f7b89984f..105419313 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -4,7 +4,7 @@ Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). -If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below. +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](), please report it to us as described below. ## Reporting Security Issues @@ -12,19 +12,19 @@ If you believe you have found a security vulnerability in any Microsoft-owned re Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). -If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). -You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: - * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) - * Full paths of source file(s) related to the manifestation of the issue - * The location of the affected source code (tag/branch/commit or direct URL) - * Any special configuration required to reproduce the issue - * Step-by-step instructions to reproduce the issue - * Proof-of-concept or exploit code (if possible) - * Impact of the issue, including how an attacker might exploit the issue +- Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) +- Full paths of source file(s) related to the manifestation of the issue +- The location of the affected source code (tag/branch/commit or direct URL) +- Any special configuration required to reproduce the issue +- Step-by-step instructions to reproduce the issue +- Proof-of-concept or exploit code (if possible) +- Impact of the issue, including how an attacker might exploit the issue This information will help us triage your report more quickly. @@ -38,4 +38,4 @@ We prefer all communications to be in English. Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). - \ No newline at end of file + diff --git a/assets/readme-banner.png b/assets/readme-banner.png new file mode 100644 index 000000000..80650f7aa Binary files /dev/null and b/assets/readme-banner.png differ diff --git a/docs/.nojekyll b/docs/.nojekyll deleted file mode 100644 index e2ac6616a..000000000 --- a/docs/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/assets/highlight.css b/docs/assets/highlight.css deleted file mode 100644 index cb086dfa5..000000000 --- a/docs/assets/highlight.css +++ /dev/null @@ -1,120 +0,0 @@ -:root { - --light-hl-0: #795E26; - --dark-hl-0: #DCDCAA; - --light-hl-1: #000000; - --dark-hl-1: #D4D4D4; - --light-hl-2: #A31515; - --dark-hl-2: #CE9178; - --light-hl-3: #0000FF; - --dark-hl-3: #569CD6; - --light-hl-4: #AF00DB; - --dark-hl-4: #C586C0; - --light-hl-5: #001080; - --dark-hl-5: #9CDCFE; - --light-hl-6: #008000; - --dark-hl-6: #6A9955; - --light-hl-7: #0070C1; - --dark-hl-7: #4FC1FF; - --light-hl-8: #800000; - --dark-hl-8: #808080; - --light-hl-9: #800000; - --dark-hl-9: #569CD6; - --light-hl-10: #E50000; - --dark-hl-10: #9CDCFE; - --light-hl-11: #0000FF; - --dark-hl-11: #CE9178; - --light-hl-12: #098658; - --dark-hl-12: #B5CEA8; - --light-hl-13: #267F99; - --dark-hl-13: #4EC9B0; - --light-code-background: #FFFFFF; - --dark-code-background: #1E1E1E; -} - -@media (prefers-color-scheme: light) { :root { - --hl-0: var(--light-hl-0); - --hl-1: var(--light-hl-1); - --hl-2: var(--light-hl-2); - --hl-3: var(--light-hl-3); - --hl-4: var(--light-hl-4); - --hl-5: var(--light-hl-5); - --hl-6: var(--light-hl-6); - --hl-7: var(--light-hl-7); - --hl-8: var(--light-hl-8); - --hl-9: var(--light-hl-9); - --hl-10: var(--light-hl-10); - --hl-11: var(--light-hl-11); - --hl-12: var(--light-hl-12); - --hl-13: var(--light-hl-13); - --code-background: var(--light-code-background); -} } - -@media (prefers-color-scheme: dark) { :root { - --hl-0: var(--dark-hl-0); - --hl-1: var(--dark-hl-1); - --hl-2: var(--dark-hl-2); - --hl-3: var(--dark-hl-3); - --hl-4: var(--dark-hl-4); - --hl-5: var(--dark-hl-5); - --hl-6: var(--dark-hl-6); - --hl-7: var(--dark-hl-7); - --hl-8: var(--dark-hl-8); - --hl-9: var(--dark-hl-9); - --hl-10: var(--dark-hl-10); - --hl-11: var(--dark-hl-11); - --hl-12: var(--dark-hl-12); - --hl-13: var(--dark-hl-13); - --code-background: var(--dark-code-background); -} } - -:root[data-theme='light'] { - --hl-0: var(--light-hl-0); - --hl-1: var(--light-hl-1); - --hl-2: var(--light-hl-2); - --hl-3: var(--light-hl-3); - --hl-4: var(--light-hl-4); - --hl-5: var(--light-hl-5); - --hl-6: var(--light-hl-6); - --hl-7: var(--light-hl-7); - --hl-8: var(--light-hl-8); - --hl-9: var(--light-hl-9); - --hl-10: var(--light-hl-10); - --hl-11: var(--light-hl-11); - --hl-12: var(--light-hl-12); - --hl-13: var(--light-hl-13); - --code-background: var(--light-code-background); -} - -:root[data-theme='dark'] { - --hl-0: var(--dark-hl-0); - --hl-1: var(--dark-hl-1); - --hl-2: var(--dark-hl-2); - --hl-3: var(--dark-hl-3); - --hl-4: var(--dark-hl-4); - --hl-5: var(--dark-hl-5); - --hl-6: var(--dark-hl-6); - --hl-7: var(--dark-hl-7); - --hl-8: var(--dark-hl-8); - --hl-9: var(--dark-hl-9); - --hl-10: var(--dark-hl-10); - --hl-11: var(--dark-hl-11); - --hl-12: var(--dark-hl-12); - --hl-13: var(--dark-hl-13); - --code-background: var(--dark-code-background); -} - -.hl-0 { color: var(--hl-0); } -.hl-1 { color: var(--hl-1); } -.hl-2 { color: var(--hl-2); } -.hl-3 { color: var(--hl-3); } -.hl-4 { color: var(--hl-4); } -.hl-5 { color: var(--hl-5); } -.hl-6 { color: var(--hl-6); } -.hl-7 { color: var(--hl-7); } -.hl-8 { color: var(--hl-8); } -.hl-9 { color: var(--hl-9); } -.hl-10 { color: var(--hl-10); } -.hl-11 { color: var(--hl-11); } -.hl-12 { color: var(--hl-12); } -.hl-13 { color: var(--hl-13); } -pre, code { background: var(--code-background); } diff --git a/docs/assets/search.js b/docs/assets/search.js deleted file mode 100644 index 86e7c85c2..000000000 --- a/docs/assets/search.js +++ /dev/null @@ -1 +0,0 @@ -window.searchData = JSON.parse("{\"rows\":[{\"kind\":2,\"name\":\"_microsoft_live_share\",\"url\":\"modules/_microsoft_live_share.html\",\"classes\":\"\"},{\"kind\":8,\"name\":\"ContainerState\",\"url\":\"enums/_microsoft_live_share.ContainerState.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":16,\"name\":\"added\",\"url\":\"enums/_microsoft_live_share.ContainerState.html#added\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ContainerState\"},{\"kind\":16,\"name\":\"alreadyExists\",\"url\":\"enums/_microsoft_live_share.ContainerState.html#alreadyExists\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ContainerState\"},{\"kind\":16,\"name\":\"conflict\",\"url\":\"enums/_microsoft_live_share.ContainerState.html#conflict\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ContainerState\"},{\"kind\":16,\"name\":\"notFound\",\"url\":\"enums/_microsoft_live_share.ContainerState.html#notFound\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ContainerState\"},{\"kind\":8,\"name\":\"FollowModeType\",\"url\":\"enums/_microsoft_live_share.FollowModeType.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":16,\"name\":\"activeFollowers\",\"url\":\"enums/_microsoft_live_share.FollowModeType.html#activeFollowers\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.FollowModeType\"},{\"kind\":16,\"name\":\"activePresenter\",\"url\":\"enums/_microsoft_live_share.FollowModeType.html#activePresenter\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.FollowModeType\"},{\"kind\":16,\"name\":\"followPresenter\",\"url\":\"enums/_microsoft_live_share.FollowModeType.html#followPresenter\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.FollowModeType\"},{\"kind\":16,\"name\":\"followUser\",\"url\":\"enums/_microsoft_live_share.FollowModeType.html#followUser\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.FollowModeType\"},{\"kind\":16,\"name\":\"local\",\"url\":\"enums/_microsoft_live_share.FollowModeType.html#local\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.FollowModeType\"},{\"kind\":16,\"name\":\"suspendFollowPresenter\",\"url\":\"enums/_microsoft_live_share.FollowModeType.html#suspendFollowPresenter\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.FollowModeType\"},{\"kind\":16,\"name\":\"suspendFollowUser\",\"url\":\"enums/_microsoft_live_share.FollowModeType.html#suspendFollowUser\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.FollowModeType\"},{\"kind\":8,\"name\":\"LiveDataObjectInitializeState\",\"url\":\"enums/_microsoft_live_share.LiveDataObjectInitializeState.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":16,\"name\":\"fatalError\",\"url\":\"enums/_microsoft_live_share.LiveDataObjectInitializeState.html#fatalError\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveDataObjectInitializeState\"},{\"kind\":16,\"name\":\"needed\",\"url\":\"enums/_microsoft_live_share.LiveDataObjectInitializeState.html#needed\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveDataObjectInitializeState\"},{\"kind\":16,\"name\":\"pending\",\"url\":\"enums/_microsoft_live_share.LiveDataObjectInitializeState.html#pending\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveDataObjectInitializeState\"},{\"kind\":16,\"name\":\"succeeded\",\"url\":\"enums/_microsoft_live_share.LiveDataObjectInitializeState.html#succeeded\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveDataObjectInitializeState\"},{\"kind\":8,\"name\":\"LiveEventEvents\",\"url\":\"enums/_microsoft_live_share.LiveEventEvents.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":16,\"name\":\"received\",\"url\":\"enums/_microsoft_live_share.LiveEventEvents.html#received\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveEventEvents\"},{\"kind\":8,\"name\":\"LiveFollowModeEvents\",\"url\":\"enums/_microsoft_live_share.LiveFollowModeEvents.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":16,\"name\":\"presenceChanged\",\"url\":\"enums/_microsoft_live_share.LiveFollowModeEvents.html#presenceChanged\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveFollowModeEvents\"},{\"kind\":16,\"name\":\"stateChanged\",\"url\":\"enums/_microsoft_live_share.LiveFollowModeEvents.html#stateChanged\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveFollowModeEvents\"},{\"kind\":8,\"name\":\"LivePresenceEvents\",\"url\":\"enums/_microsoft_live_share.LivePresenceEvents.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":16,\"name\":\"presenceChanged\",\"url\":\"enums/_microsoft_live_share.LivePresenceEvents.html#presenceChanged\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LivePresenceEvents\"},{\"kind\":8,\"name\":\"LiveStateEvents\",\"url\":\"enums/_microsoft_live_share.LiveStateEvents.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":16,\"name\":\"stateChanged\",\"url\":\"enums/_microsoft_live_share.LiveStateEvents.html#stateChanged\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveStateEvents\"},{\"kind\":8,\"name\":\"LiveTimerEvents\",\"url\":\"enums/_microsoft_live_share.LiveTimerEvents.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":16,\"name\":\"finished\",\"url\":\"enums/_microsoft_live_share.LiveTimerEvents.html#finished\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveTimerEvents\"},{\"kind\":16,\"name\":\"onTick\",\"url\":\"enums/_microsoft_live_share.LiveTimerEvents.html#onTick\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveTimerEvents\"},{\"kind\":16,\"name\":\"paused\",\"url\":\"enums/_microsoft_live_share.LiveTimerEvents.html#paused\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveTimerEvents\"},{\"kind\":16,\"name\":\"played\",\"url\":\"enums/_microsoft_live_share.LiveTimerEvents.html#played\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveTimerEvents\"},{\"kind\":16,\"name\":\"started\",\"url\":\"enums/_microsoft_live_share.LiveTimerEvents.html#started\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveTimerEvents\"},{\"kind\":8,\"name\":\"PresenceState\",\"url\":\"enums/_microsoft_live_share.PresenceState.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":16,\"name\":\"away\",\"url\":\"enums/_microsoft_live_share.PresenceState.html#away\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.PresenceState\"},{\"kind\":16,\"name\":\"offline\",\"url\":\"enums/_microsoft_live_share.PresenceState.html#offline\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.PresenceState\"},{\"kind\":16,\"name\":\"online\",\"url\":\"enums/_microsoft_live_share.PresenceState.html#online\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.PresenceState\"},{\"kind\":8,\"name\":\"UserMeetingRole\",\"url\":\"enums/_microsoft_live_share.UserMeetingRole.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":16,\"name\":\"attendee\",\"url\":\"enums/_microsoft_live_share.UserMeetingRole.html#attendee\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.UserMeetingRole\"},{\"kind\":16,\"name\":\"guest\",\"url\":\"enums/_microsoft_live_share.UserMeetingRole.html#guest\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.UserMeetingRole\"},{\"kind\":16,\"name\":\"organizer\",\"url\":\"enums/_microsoft_live_share.UserMeetingRole.html#organizer\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.UserMeetingRole\"},{\"kind\":16,\"name\":\"presenter\",\"url\":\"enums/_microsoft_live_share.UserMeetingRole.html#presenter\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.UserMeetingRole\"},{\"kind\":128,\"name\":\"AzureLiveShareHost\",\"url\":\"classes/_microsoft_live_share.AzureLiveShareHost.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":2048,\"name\":\"getClientInfo\",\"url\":\"classes/_microsoft_live_share.AzureLiveShareHost.html#getClientInfo\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.AzureLiveShareHost\"},{\"kind\":2048,\"name\":\"getClientRoles\",\"url\":\"classes/_microsoft_live_share.AzureLiveShareHost.html#getClientRoles\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.AzureLiveShareHost\"},{\"kind\":2048,\"name\":\"getFluidContainerId\",\"url\":\"classes/_microsoft_live_share.AzureLiveShareHost.html#getFluidContainerId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.AzureLiveShareHost\"},{\"kind\":2048,\"name\":\"getFluidTenantInfo\",\"url\":\"classes/_microsoft_live_share.AzureLiveShareHost.html#getFluidTenantInfo\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.AzureLiveShareHost\"},{\"kind\":2048,\"name\":\"getFluidToken\",\"url\":\"classes/_microsoft_live_share.AzureLiveShareHost.html#getFluidToken\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.AzureLiveShareHost\"},{\"kind\":2048,\"name\":\"getNtpTime\",\"url\":\"classes/_microsoft_live_share.AzureLiveShareHost.html#getNtpTime\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.AzureLiveShareHost\"},{\"kind\":2048,\"name\":\"registerClientId\",\"url\":\"classes/_microsoft_live_share.AzureLiveShareHost.html#registerClientId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.AzureLiveShareHost\"},{\"kind\":2048,\"name\":\"setAudience\",\"url\":\"classes/_microsoft_live_share.AzureLiveShareHost.html#setAudience\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.AzureLiveShareHost\"},{\"kind\":2048,\"name\":\"setFluidContainerId\",\"url\":\"classes/_microsoft_live_share.AzureLiveShareHost.html#setFluidContainerId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.AzureLiveShareHost\"},{\"kind\":2048,\"name\":\"create\",\"url\":\"classes/_microsoft_live_share.AzureLiveShareHost.html#create\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.AzureLiveShareHost\"},{\"kind\":128,\"name\":\"DynamicObjectRegistry\",\"url\":\"classes/_microsoft_live_share.DynamicObjectRegistry.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share.DynamicObjectRegistry.html#constructor\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.DynamicObjectRegistry\"},{\"kind\":262144,\"name\":\"dynamicLoadableObjects\",\"url\":\"classes/_microsoft_live_share.DynamicObjectRegistry.html#dynamicLoadableObjects\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.DynamicObjectRegistry\"},{\"kind\":2048,\"name\":\"registerObjectClass\",\"url\":\"classes/_microsoft_live_share.DynamicObjectRegistry.html#registerObjectClass\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.DynamicObjectRegistry\"},{\"kind\":128,\"name\":\"HostTimestampProvider\",\"url\":\"classes/_microsoft_live_share.HostTimestampProvider.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share.HostTimestampProvider.html#constructor\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.HostTimestampProvider\"},{\"kind\":262144,\"name\":\"isRunning\",\"url\":\"classes/_microsoft_live_share.HostTimestampProvider.html#isRunning\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.HostTimestampProvider\"},{\"kind\":2048,\"name\":\"getMaxTimestampError\",\"url\":\"classes/_microsoft_live_share.HostTimestampProvider.html#getMaxTimestampError\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.HostTimestampProvider\"},{\"kind\":2048,\"name\":\"getNtpTime\",\"url\":\"classes/_microsoft_live_share.HostTimestampProvider.html#getNtpTime\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share.HostTimestampProvider\"},{\"kind\":2048,\"name\":\"getTimestamp\",\"url\":\"classes/_microsoft_live_share.HostTimestampProvider.html#getTimestamp\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.HostTimestampProvider\"},{\"kind\":2048,\"name\":\"start\",\"url\":\"classes/_microsoft_live_share.HostTimestampProvider.html#start\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.HostTimestampProvider\"},{\"kind\":2048,\"name\":\"stop\",\"url\":\"classes/_microsoft_live_share.HostTimestampProvider.html#stop\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.HostTimestampProvider\"},{\"kind\":128,\"name\":\"LiveDataObject\",\"url\":\"classes/_microsoft_live_share.LiveDataObject.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share.LiveDataObject.html#constructor\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveDataObject\"},{\"kind\":262144,\"name\":\"initializeState\",\"url\":\"classes/_microsoft_live_share.LiveDataObject.html#initializeState\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveDataObject\"},{\"kind\":262144,\"name\":\"isInitialized\",\"url\":\"classes/_microsoft_live_share.LiveDataObject.html#isInitialized\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveDataObject\"},{\"kind\":2048,\"name\":\"getClientInfo\",\"url\":\"classes/_microsoft_live_share.LiveDataObject.html#getClientInfo\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveDataObject\"},{\"kind\":2048,\"name\":\"verifyLocalUserRoles\",\"url\":\"classes/_microsoft_live_share.LiveDataObject.html#verifyLocalUserRoles\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share.LiveDataObject\"},{\"kind\":2048,\"name\":\"waitUntilConnected\",\"url\":\"classes/_microsoft_live_share.LiveDataObject.html#waitUntilConnected\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share.LiveDataObject\"},{\"kind\":128,\"name\":\"LiveEvent\",\"url\":\"classes/_microsoft_live_share.LiveEvent.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share.LiveEvent.html#constructor\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LiveEvent\"},{\"kind\":1024,\"name\":\"TypeName\",\"url\":\"classes/_microsoft_live_share.LiveEvent.html#TypeName\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveEvent\"},{\"kind\":1024,\"name\":\"factory\",\"url\":\"classes/_microsoft_live_share.LiveEvent.html#factory\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveEvent\"},{\"kind\":262144,\"name\":\"initializeState\",\"url\":\"classes/_microsoft_live_share.LiveEvent.html#initializeState\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LiveEvent\"},{\"kind\":262144,\"name\":\"isInitialized\",\"url\":\"classes/_microsoft_live_share.LiveEvent.html#isInitialized\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LiveEvent\"},{\"kind\":2048,\"name\":\"getClientInfo\",\"url\":\"classes/_microsoft_live_share.LiveEvent.html#getClientInfo\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LiveEvent\"},{\"kind\":2048,\"name\":\"initialize\",\"url\":\"classes/_microsoft_live_share.LiveEvent.html#initialize\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveEvent\"},{\"kind\":2048,\"name\":\"send\",\"url\":\"classes/_microsoft_live_share.LiveEvent.html#send\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveEvent\"},{\"kind\":2048,\"name\":\"verifyLocalUserRoles\",\"url\":\"classes/_microsoft_live_share.LiveEvent.html#verifyLocalUserRoles\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LiveEvent\"},{\"kind\":2048,\"name\":\"waitUntilConnected\",\"url\":\"classes/_microsoft_live_share.LiveEvent.html#waitUntilConnected\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LiveEvent\"},{\"kind\":2048,\"name\":\"isNewer\",\"url\":\"classes/_microsoft_live_share.LiveEvent.html#isNewer\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveEvent\"},{\"kind\":128,\"name\":\"LiveEventScope\",\"url\":\"classes/_microsoft_live_share.LiveEventScope.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share.LiveEventScope.html#constructor\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveEventScope\"},{\"kind\":262144,\"name\":\"allowedRoles\",\"url\":\"classes/_microsoft_live_share.LiveEventScope.html#allowedRoles\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveEventScope\"},{\"kind\":262144,\"name\":\"clientId\",\"url\":\"classes/_microsoft_live_share.LiveEventScope.html#clientId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveEventScope\"},{\"kind\":2048,\"name\":\"offEvent\",\"url\":\"classes/_microsoft_live_share.LiveEventScope.html#offEvent\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveEventScope\"},{\"kind\":2048,\"name\":\"onEvent\",\"url\":\"classes/_microsoft_live_share.LiveEventScope.html#onEvent\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveEventScope\"},{\"kind\":2048,\"name\":\"sendEvent\",\"url\":\"classes/_microsoft_live_share.LiveEventScope.html#sendEvent\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveEventScope\"},{\"kind\":128,\"name\":\"LiveEventSource\",\"url\":\"classes/_microsoft_live_share.LiveEventSource.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share.LiveEventSource.html#constructor\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveEventSource\"},{\"kind\":2048,\"name\":\"sendEvent\",\"url\":\"classes/_microsoft_live_share.LiveEventSource.html#sendEvent\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveEventSource\"},{\"kind\":128,\"name\":\"LiveEventTarget\",\"url\":\"classes/_microsoft_live_share.LiveEventTarget.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share.LiveEventTarget.html#constructor\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveEventTarget\"},{\"kind\":2048,\"name\":\"sendEvent\",\"url\":\"classes/_microsoft_live_share.LiveEventTarget.html#sendEvent\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LiveEventTarget\"},{\"kind\":128,\"name\":\"LiveEventTimer\",\"url\":\"classes/_microsoft_live_share.LiveEventTimer.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share.LiveEventTimer.html#constructor\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveEventTimer\"},{\"kind\":1024,\"name\":\"repeat\",\"url\":\"classes/_microsoft_live_share.LiveEventTimer.html#repeat\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveEventTimer\"},{\"kind\":262144,\"name\":\"delay\",\"url\":\"classes/_microsoft_live_share.LiveEventTimer.html#delay\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveEventTimer\"},{\"kind\":262144,\"name\":\"isRunning\",\"url\":\"classes/_microsoft_live_share.LiveEventTimer.html#isRunning\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveEventTimer\"},{\"kind\":2048,\"name\":\"sendEvent\",\"url\":\"classes/_microsoft_live_share.LiveEventTimer.html#sendEvent\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveEventTimer\"},{\"kind\":2048,\"name\":\"start\",\"url\":\"classes/_microsoft_live_share.LiveEventTimer.html#start\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveEventTimer\"},{\"kind\":2048,\"name\":\"stop\",\"url\":\"classes/_microsoft_live_share.LiveEventTimer.html#stop\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveEventTimer\"},{\"kind\":128,\"name\":\"LiveFollowMode\",\"url\":\"classes/_microsoft_live_share.LiveFollowMode.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share.LiveFollowMode.html#constructor\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LiveFollowMode\"},{\"kind\":1024,\"name\":\"TypeName\",\"url\":\"classes/_microsoft_live_share.LiveFollowMode.html#TypeName\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveFollowMode\"},{\"kind\":1024,\"name\":\"factory\",\"url\":\"classes/_microsoft_live_share.LiveFollowMode.html#factory\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveFollowMode\"},{\"kind\":262144,\"name\":\"initializeState\",\"url\":\"classes/_microsoft_live_share.LiveFollowMode.html#initializeState\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LiveFollowMode\"},{\"kind\":262144,\"name\":\"isInitialized\",\"url\":\"classes/_microsoft_live_share.LiveFollowMode.html#isInitialized\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LiveFollowMode\"},{\"kind\":262144,\"name\":\"localUser\",\"url\":\"classes/_microsoft_live_share.LiveFollowMode.html#localUser\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveFollowMode\"},{\"kind\":262144,\"name\":\"state\",\"url\":\"classes/_microsoft_live_share.LiveFollowMode.html#state\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveFollowMode\"},{\"kind\":2048,\"name\":\"beginSuspension\",\"url\":\"classes/_microsoft_live_share.LiveFollowMode.html#beginSuspension\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveFollowMode\"},{\"kind\":2048,\"name\":\"dispose\",\"url\":\"classes/_microsoft_live_share.LiveFollowMode.html#dispose\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveFollowMode\"},{\"kind\":2048,\"name\":\"endSuspension\",\"url\":\"classes/_microsoft_live_share.LiveFollowMode.html#endSuspension\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveFollowMode\"},{\"kind\":2048,\"name\":\"followUser\",\"url\":\"classes/_microsoft_live_share.LiveFollowMode.html#followUser\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveFollowMode\"},{\"kind\":2048,\"name\":\"getClientInfo\",\"url\":\"classes/_microsoft_live_share.LiveFollowMode.html#getClientInfo\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LiveFollowMode\"},{\"kind\":2048,\"name\":\"getUser\",\"url\":\"classes/_microsoft_live_share.LiveFollowMode.html#getUser\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveFollowMode\"},{\"kind\":2048,\"name\":\"getUserFollowers\",\"url\":\"classes/_microsoft_live_share.LiveFollowMode.html#getUserFollowers\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveFollowMode\"},{\"kind\":2048,\"name\":\"getUserForClient\",\"url\":\"classes/_microsoft_live_share.LiveFollowMode.html#getUserForClient\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveFollowMode\"},{\"kind\":2048,\"name\":\"getUsers\",\"url\":\"classes/_microsoft_live_share.LiveFollowMode.html#getUsers\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveFollowMode\"},{\"kind\":2048,\"name\":\"hasInitialized\",\"url\":\"classes/_microsoft_live_share.LiveFollowMode.html#hasInitialized\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share.LiveFollowMode\"},{\"kind\":2048,\"name\":\"initialize\",\"url\":\"classes/_microsoft_live_share.LiveFollowMode.html#initialize\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveFollowMode\"},{\"kind\":2048,\"name\":\"initializingFirstTime\",\"url\":\"classes/_microsoft_live_share.LiveFollowMode.html#initializingFirstTime\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share.LiveFollowMode\"},{\"kind\":2048,\"name\":\"startPresenting\",\"url\":\"classes/_microsoft_live_share.LiveFollowMode.html#startPresenting\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveFollowMode\"},{\"kind\":2048,\"name\":\"stopFollowing\",\"url\":\"classes/_microsoft_live_share.LiveFollowMode.html#stopFollowing\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveFollowMode\"},{\"kind\":2048,\"name\":\"stopPresenting\",\"url\":\"classes/_microsoft_live_share.LiveFollowMode.html#stopPresenting\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveFollowMode\"},{\"kind\":2048,\"name\":\"update\",\"url\":\"classes/_microsoft_live_share.LiveFollowMode.html#update\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveFollowMode\"},{\"kind\":2048,\"name\":\"verifyLocalUserRoles\",\"url\":\"classes/_microsoft_live_share.LiveFollowMode.html#verifyLocalUserRoles\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LiveFollowMode\"},{\"kind\":2048,\"name\":\"waitUntilConnected\",\"url\":\"classes/_microsoft_live_share.LiveFollowMode.html#waitUntilConnected\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LiveFollowMode\"},{\"kind\":128,\"name\":\"LivePresence\",\"url\":\"classes/_microsoft_live_share.LivePresence.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share.LivePresence.html#constructor\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LivePresence\"},{\"kind\":1024,\"name\":\"TypeName\",\"url\":\"classes/_microsoft_live_share.LivePresence.html#TypeName\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LivePresence\"},{\"kind\":1024,\"name\":\"factory\",\"url\":\"classes/_microsoft_live_share.LivePresence.html#factory\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LivePresence\"},{\"kind\":262144,\"name\":\"expirationPeriod\",\"url\":\"classes/_microsoft_live_share.LivePresence.html#expirationPeriod\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LivePresence\"},{\"kind\":262144,\"name\":\"initializeState\",\"url\":\"classes/_microsoft_live_share.LivePresence.html#initializeState\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LivePresence\"},{\"kind\":262144,\"name\":\"isInitialized\",\"url\":\"classes/_microsoft_live_share.LivePresence.html#isInitialized\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LivePresence\"},{\"kind\":262144,\"name\":\"localUser\",\"url\":\"classes/_microsoft_live_share.LivePresence.html#localUser\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LivePresence\"},{\"kind\":2048,\"name\":\"dispose\",\"url\":\"classes/_microsoft_live_share.LivePresence.html#dispose\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LivePresence\"},{\"kind\":2048,\"name\":\"getClientInfo\",\"url\":\"classes/_microsoft_live_share.LivePresence.html#getClientInfo\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LivePresence\"},{\"kind\":2048,\"name\":\"getUser\",\"url\":\"classes/_microsoft_live_share.LivePresence.html#getUser\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LivePresence\"},{\"kind\":2048,\"name\":\"getUserForClient\",\"url\":\"classes/_microsoft_live_share.LivePresence.html#getUserForClient\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LivePresence\"},{\"kind\":2048,\"name\":\"getUsers\",\"url\":\"classes/_microsoft_live_share.LivePresence.html#getUsers\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LivePresence\"},{\"kind\":2048,\"name\":\"initialize\",\"url\":\"classes/_microsoft_live_share.LivePresence.html#initialize\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LivePresence\"},{\"kind\":2048,\"name\":\"update\",\"url\":\"classes/_microsoft_live_share.LivePresence.html#update\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LivePresence\"},{\"kind\":2048,\"name\":\"verifyLocalUserRoles\",\"url\":\"classes/_microsoft_live_share.LivePresence.html#verifyLocalUserRoles\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LivePresence\"},{\"kind\":2048,\"name\":\"waitUntilConnected\",\"url\":\"classes/_microsoft_live_share.LivePresence.html#waitUntilConnected\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LivePresence\"},{\"kind\":128,\"name\":\"LivePresenceUser\",\"url\":\"classes/_microsoft_live_share.LivePresenceUser.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":262144,\"name\":\"data\",\"url\":\"classes/_microsoft_live_share.LivePresenceUser.html#data\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LivePresenceUser\"},{\"kind\":262144,\"name\":\"displayName\",\"url\":\"classes/_microsoft_live_share.LivePresenceUser.html#displayName\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LivePresenceUser\"},{\"kind\":262144,\"name\":\"isLocalUser\",\"url\":\"classes/_microsoft_live_share.LivePresenceUser.html#isLocalUser\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LivePresenceUser\"},{\"kind\":262144,\"name\":\"roles\",\"url\":\"classes/_microsoft_live_share.LivePresenceUser.html#roles\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LivePresenceUser\"},{\"kind\":262144,\"name\":\"state\",\"url\":\"classes/_microsoft_live_share.LivePresenceUser.html#state\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LivePresenceUser\"},{\"kind\":262144,\"name\":\"userId\",\"url\":\"classes/_microsoft_live_share.LivePresenceUser.html#userId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LivePresenceUser\"},{\"kind\":2048,\"name\":\"getConnection\",\"url\":\"classes/_microsoft_live_share.LivePresenceUser.html#getConnection\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LivePresenceUser\"},{\"kind\":2048,\"name\":\"getConnections\",\"url\":\"classes/_microsoft_live_share.LivePresenceUser.html#getConnections\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LivePresenceUser\"},{\"kind\":2048,\"name\":\"isFromClient\",\"url\":\"classes/_microsoft_live_share.LivePresenceUser.html#isFromClient\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LivePresenceUser\"},{\"kind\":128,\"name\":\"LiveShareClient\",\"url\":\"classes/_microsoft_live_share.LiveShareClient.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share.LiveShareClient.html#constructor\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveShareClient\"},{\"kind\":1024,\"name\":\"maxContainerLookupTries\",\"url\":\"classes/_microsoft_live_share.LiveShareClient.html#maxContainerLookupTries\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveShareClient\"},{\"kind\":262144,\"name\":\"canSendBackgroundUpdates\",\"url\":\"classes/_microsoft_live_share.LiveShareClient.html#canSendBackgroundUpdates\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveShareClient\"},{\"kind\":262144,\"name\":\"isTesting\",\"url\":\"classes/_microsoft_live_share.LiveShareClient.html#isTesting\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveShareClient\"},{\"kind\":2048,\"name\":\"joinContainer\",\"url\":\"classes/_microsoft_live_share.LiveShareClient.html#joinContainer\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveShareClient\"},{\"kind\":128,\"name\":\"LiveShareRuntime\",\"url\":\"classes/_microsoft_live_share.LiveShareRuntime.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share.LiveShareRuntime.html#constructor\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveShareRuntime\"},{\"kind\":1024,\"name\":\"_containerRuntime\",\"url\":\"classes/_microsoft_live_share.LiveShareRuntime.html#_containerRuntime\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share.LiveShareRuntime\"},{\"kind\":262144,\"name\":\"canSendBackgroundUpdates\",\"url\":\"classes/_microsoft_live_share.LiveShareRuntime.html#canSendBackgroundUpdates\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveShareRuntime\"},{\"kind\":262144,\"name\":\"host\",\"url\":\"classes/_microsoft_live_share.LiveShareRuntime.html#host\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveShareRuntime\"},{\"kind\":262144,\"name\":\"objectManager\",\"url\":\"classes/_microsoft_live_share.LiveShareRuntime.html#objectManager\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveShareRuntime\"},{\"kind\":262144,\"name\":\"timestampProvider\",\"url\":\"classes/_microsoft_live_share.LiveShareRuntime.html#timestampProvider\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveShareRuntime\"},{\"kind\":2048,\"name\":\"getClientInfo\",\"url\":\"classes/_microsoft_live_share.LiveShareRuntime.html#getClientInfo\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveShareRuntime\"},{\"kind\":2048,\"name\":\"getTimestamp\",\"url\":\"classes/_microsoft_live_share.LiveShareRuntime.html#getTimestamp\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveShareRuntime\"},{\"kind\":2048,\"name\":\"setAudience\",\"url\":\"classes/_microsoft_live_share.LiveShareRuntime.html#setAudience\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveShareRuntime\"},{\"kind\":2048,\"name\":\"setHost\",\"url\":\"classes/_microsoft_live_share.LiveShareRuntime.html#setHost\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveShareRuntime\"},{\"kind\":2048,\"name\":\"start\",\"url\":\"classes/_microsoft_live_share.LiveShareRuntime.html#start\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveShareRuntime\"},{\"kind\":2048,\"name\":\"stop\",\"url\":\"classes/_microsoft_live_share.LiveShareRuntime.html#stop\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveShareRuntime\"},{\"kind\":2048,\"name\":\"verifyRolesAllowed\",\"url\":\"classes/_microsoft_live_share.LiveShareRuntime.html#verifyRolesAllowed\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveShareRuntime\"},{\"kind\":128,\"name\":\"LiveState\",\"url\":\"classes/_microsoft_live_share.LiveState.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share.LiveState.html#constructor\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LiveState\"},{\"kind\":1024,\"name\":\"TypeName\",\"url\":\"classes/_microsoft_live_share.LiveState.html#TypeName\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveState\"},{\"kind\":1024,\"name\":\"factory\",\"url\":\"classes/_microsoft_live_share.LiveState.html#factory\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveState\"},{\"kind\":262144,\"name\":\"initializeState\",\"url\":\"classes/_microsoft_live_share.LiveState.html#initializeState\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LiveState\"},{\"kind\":262144,\"name\":\"isInitialized\",\"url\":\"classes/_microsoft_live_share.LiveState.html#isInitialized\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LiveState\"},{\"kind\":262144,\"name\":\"state\",\"url\":\"classes/_microsoft_live_share.LiveState.html#state\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveState\"},{\"kind\":2048,\"name\":\"dispose\",\"url\":\"classes/_microsoft_live_share.LiveState.html#dispose\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveState\"},{\"kind\":2048,\"name\":\"getClientInfo\",\"url\":\"classes/_microsoft_live_share.LiveState.html#getClientInfo\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LiveState\"},{\"kind\":2048,\"name\":\"initialize\",\"url\":\"classes/_microsoft_live_share.LiveState.html#initialize\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveState\"},{\"kind\":2048,\"name\":\"set\",\"url\":\"classes/_microsoft_live_share.LiveState.html#set\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveState\"},{\"kind\":2048,\"name\":\"verifyLocalUserRoles\",\"url\":\"classes/_microsoft_live_share.LiveState.html#verifyLocalUserRoles\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LiveState\"},{\"kind\":2048,\"name\":\"waitUntilConnected\",\"url\":\"classes/_microsoft_live_share.LiveState.html#waitUntilConnected\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LiveState\"},{\"kind\":128,\"name\":\"LiveTelemetryLogger\",\"url\":\"classes/_microsoft_live_share.LiveTelemetryLogger.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share.LiveTelemetryLogger.html#constructor\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveTelemetryLogger\"},{\"kind\":2048,\"name\":\"sendErrorEvent\",\"url\":\"classes/_microsoft_live_share.LiveTelemetryLogger.html#sendErrorEvent\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveTelemetryLogger\"},{\"kind\":2048,\"name\":\"sendPerformanceEvent\",\"url\":\"classes/_microsoft_live_share.LiveTelemetryLogger.html#sendPerformanceEvent\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveTelemetryLogger\"},{\"kind\":2048,\"name\":\"sendTelemetryEvent\",\"url\":\"classes/_microsoft_live_share.LiveTelemetryLogger.html#sendTelemetryEvent\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveTelemetryLogger\"},{\"kind\":2048,\"name\":\"formatCorrelationId\",\"url\":\"classes/_microsoft_live_share.LiveTelemetryLogger.html#formatCorrelationId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveTelemetryLogger\"},{\"kind\":128,\"name\":\"LiveTimer\",\"url\":\"classes/_microsoft_live_share.LiveTimer.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share.LiveTimer.html#constructor\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LiveTimer\"},{\"kind\":1024,\"name\":\"TypeName\",\"url\":\"classes/_microsoft_live_share.LiveTimer.html#TypeName\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveTimer\"},{\"kind\":1024,\"name\":\"factory\",\"url\":\"classes/_microsoft_live_share.LiveTimer.html#factory\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveTimer\"},{\"kind\":262144,\"name\":\"initializeState\",\"url\":\"classes/_microsoft_live_share.LiveTimer.html#initializeState\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LiveTimer\"},{\"kind\":262144,\"name\":\"isInitialized\",\"url\":\"classes/_microsoft_live_share.LiveTimer.html#isInitialized\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LiveTimer\"},{\"kind\":262144,\"name\":\"tickRate\",\"url\":\"classes/_microsoft_live_share.LiveTimer.html#tickRate\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveTimer\"},{\"kind\":2048,\"name\":\"dispose\",\"url\":\"classes/_microsoft_live_share.LiveTimer.html#dispose\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveTimer\"},{\"kind\":2048,\"name\":\"getClientInfo\",\"url\":\"classes/_microsoft_live_share.LiveTimer.html#getClientInfo\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LiveTimer\"},{\"kind\":2048,\"name\":\"initialize\",\"url\":\"classes/_microsoft_live_share.LiveTimer.html#initialize\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveTimer\"},{\"kind\":2048,\"name\":\"pause\",\"url\":\"classes/_microsoft_live_share.LiveTimer.html#pause\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveTimer\"},{\"kind\":2048,\"name\":\"play\",\"url\":\"classes/_microsoft_live_share.LiveTimer.html#play\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveTimer\"},{\"kind\":2048,\"name\":\"start\",\"url\":\"classes/_microsoft_live_share.LiveTimer.html#start\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveTimer\"},{\"kind\":2048,\"name\":\"verifyLocalUserRoles\",\"url\":\"classes/_microsoft_live_share.LiveTimer.html#verifyLocalUserRoles\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LiveTimer\"},{\"kind\":2048,\"name\":\"waitUntilConnected\",\"url\":\"classes/_microsoft_live_share.LiveTimer.html#waitUntilConnected\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share.LiveTimer\"},{\"kind\":128,\"name\":\"LocalTimestampProvider\",\"url\":\"classes/_microsoft_live_share.LocalTimestampProvider.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share.LocalTimestampProvider.html#constructor\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LocalTimestampProvider\"},{\"kind\":2048,\"name\":\"getMaxTimestampError\",\"url\":\"classes/_microsoft_live_share.LocalTimestampProvider.html#getMaxTimestampError\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LocalTimestampProvider\"},{\"kind\":2048,\"name\":\"getTimestamp\",\"url\":\"classes/_microsoft_live_share.LocalTimestampProvider.html#getTimestamp\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LocalTimestampProvider\"},{\"kind\":128,\"name\":\"TestLiveShareHost\",\"url\":\"classes/_microsoft_live_share.TestLiveShareHost.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":1024,\"name\":\"defaultLocalRoles\",\"url\":\"classes/_microsoft_live_share.TestLiveShareHost.html#defaultLocalRoles\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.TestLiveShareHost\"},{\"kind\":1024,\"name\":\"defaultRemoteRoles\",\"url\":\"classes/_microsoft_live_share.TestLiveShareHost.html#defaultRemoteRoles\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.TestLiveShareHost\"},{\"kind\":1024,\"name\":\"LOCAL_MODE_TEST_TOKEN\",\"url\":\"classes/_microsoft_live_share.TestLiveShareHost.html#LOCAL_MODE_TEST_TOKEN\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.TestLiveShareHost\"},{\"kind\":2048,\"name\":\"addClient\",\"url\":\"classes/_microsoft_live_share.TestLiveShareHost.html#addClient\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.TestLiveShareHost\"},{\"kind\":2048,\"name\":\"getClientInfo\",\"url\":\"classes/_microsoft_live_share.TestLiveShareHost.html#getClientInfo\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.TestLiveShareHost\"},{\"kind\":2048,\"name\":\"getClientRoles\",\"url\":\"classes/_microsoft_live_share.TestLiveShareHost.html#getClientRoles\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.TestLiveShareHost\"},{\"kind\":2048,\"name\":\"getFluidContainerId\",\"url\":\"classes/_microsoft_live_share.TestLiveShareHost.html#getFluidContainerId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.TestLiveShareHost\"},{\"kind\":2048,\"name\":\"getFluidTenantInfo\",\"url\":\"classes/_microsoft_live_share.TestLiveShareHost.html#getFluidTenantInfo\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.TestLiveShareHost\"},{\"kind\":2048,\"name\":\"getFluidToken\",\"url\":\"classes/_microsoft_live_share.TestLiveShareHost.html#getFluidToken\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.TestLiveShareHost\"},{\"kind\":2048,\"name\":\"getNtpTime\",\"url\":\"classes/_microsoft_live_share.TestLiveShareHost.html#getNtpTime\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.TestLiveShareHost\"},{\"kind\":2048,\"name\":\"registerClientId\",\"url\":\"classes/_microsoft_live_share.TestLiveShareHost.html#registerClientId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.TestLiveShareHost\"},{\"kind\":2048,\"name\":\"setFluidContainerId\",\"url\":\"classes/_microsoft_live_share.TestLiveShareHost.html#setFluidContainerId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.TestLiveShareHost\"},{\"kind\":2048,\"name\":\"create\",\"url\":\"classes/_microsoft_live_share.TestLiveShareHost.html#create\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.TestLiveShareHost\"},{\"kind\":128,\"name\":\"TimestampProvider\",\"url\":\"classes/_microsoft_live_share.TimestampProvider.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share.TimestampProvider.html#constructor\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.TimestampProvider\"},{\"kind\":262144,\"name\":\"isRunning\",\"url\":\"classes/_microsoft_live_share.TimestampProvider.html#isRunning\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.TimestampProvider\"},{\"kind\":2048,\"name\":\"getMaxTimestampError\",\"url\":\"classes/_microsoft_live_share.TimestampProvider.html#getMaxTimestampError\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.TimestampProvider\"},{\"kind\":2048,\"name\":\"getNtpTime\",\"url\":\"classes/_microsoft_live_share.TimestampProvider.html#getNtpTime\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share.TimestampProvider\"},{\"kind\":2048,\"name\":\"getTimestamp\",\"url\":\"classes/_microsoft_live_share.TimestampProvider.html#getTimestamp\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.TimestampProvider\"},{\"kind\":2048,\"name\":\"start\",\"url\":\"classes/_microsoft_live_share.TimestampProvider.html#start\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.TimestampProvider\"},{\"kind\":2048,\"name\":\"stop\",\"url\":\"classes/_microsoft_live_share.TimestampProvider.html#stop\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.TimestampProvider\"},{\"kind\":256,\"name\":\"IClientInfo\",\"url\":\"interfaces/_microsoft_live_share.IClientInfo.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":1024,\"name\":\"displayName\",\"url\":\"interfaces/_microsoft_live_share.IClientInfo.html#displayName\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.IClientInfo\"},{\"kind\":1024,\"name\":\"roles\",\"url\":\"interfaces/_microsoft_live_share.IClientInfo.html#roles\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.IClientInfo\"},{\"kind\":1024,\"name\":\"userId\",\"url\":\"interfaces/_microsoft_live_share.IClientInfo.html#userId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.IClientInfo\"},{\"kind\":256,\"name\":\"IClientTimestamp\",\"url\":\"interfaces/_microsoft_live_share.IClientTimestamp.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":1024,\"name\":\"clientId\",\"url\":\"interfaces/_microsoft_live_share.IClientTimestamp.html#clientId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.IClientTimestamp\"},{\"kind\":1024,\"name\":\"timestamp\",\"url\":\"interfaces/_microsoft_live_share.IClientTimestamp.html#timestamp\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.IClientTimestamp\"},{\"kind\":256,\"name\":\"IContainerRuntimeSignaler\",\"url\":\"interfaces/_microsoft_live_share.IContainerRuntimeSignaler.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":2048,\"name\":\"off\",\"url\":\"interfaces/_microsoft_live_share.IContainerRuntimeSignaler.html#off\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.IContainerRuntimeSignaler\"},{\"kind\":2048,\"name\":\"on\",\"url\":\"interfaces/_microsoft_live_share.IContainerRuntimeSignaler.html#on\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.IContainerRuntimeSignaler\"},{\"kind\":2048,\"name\":\"submitSignal\",\"url\":\"interfaces/_microsoft_live_share.IContainerRuntimeSignaler.html#submitSignal\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.IContainerRuntimeSignaler\"},{\"kind\":256,\"name\":\"IEvent\",\"url\":\"interfaces/_microsoft_live_share.IEvent.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":1024,\"name\":\"name\",\"url\":\"interfaces/_microsoft_live_share.IEvent.html#name\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.IEvent\"},{\"kind\":256,\"name\":\"IFluidContainerInfo\",\"url\":\"interfaces/_microsoft_live_share.IFluidContainerInfo.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":1024,\"name\":\"containerId\",\"url\":\"interfaces/_microsoft_live_share.IFluidContainerInfo.html#containerId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.IFluidContainerInfo\"},{\"kind\":1024,\"name\":\"containerState\",\"url\":\"interfaces/_microsoft_live_share.IFluidContainerInfo.html#containerState\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.IFluidContainerInfo\"},{\"kind\":1024,\"name\":\"retryAfter\",\"url\":\"interfaces/_microsoft_live_share.IFluidContainerInfo.html#retryAfter\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.IFluidContainerInfo\"},{\"kind\":1024,\"name\":\"shouldCreate\",\"url\":\"interfaces/_microsoft_live_share.IFluidContainerInfo.html#shouldCreate\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.IFluidContainerInfo\"},{\"kind\":256,\"name\":\"IFluidTenantInfo\",\"url\":\"interfaces/_microsoft_live_share.IFluidTenantInfo.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":1024,\"name\":\"serviceEndpoint\",\"url\":\"interfaces/_microsoft_live_share.IFluidTenantInfo.html#serviceEndpoint\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.IFluidTenantInfo\"},{\"kind\":1024,\"name\":\"tenantId\",\"url\":\"interfaces/_microsoft_live_share.IFluidTenantInfo.html#tenantId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.IFluidTenantInfo\"},{\"kind\":256,\"name\":\"IFollowModePresenceUserData\",\"url\":\"interfaces/_microsoft_live_share.IFollowModePresenceUserData.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":1024,\"name\":\"followingUserId\",\"url\":\"interfaces/_microsoft_live_share.IFollowModePresenceUserData.html#followingUserId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.IFollowModePresenceUserData\"},{\"kind\":1024,\"name\":\"stateValue\",\"url\":\"interfaces/_microsoft_live_share.IFollowModePresenceUserData.html#stateValue\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.IFollowModePresenceUserData\"},{\"kind\":256,\"name\":\"IFollowModeState\",\"url\":\"interfaces/_microsoft_live_share.IFollowModeState.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":1024,\"name\":\"followingUserId\",\"url\":\"interfaces/_microsoft_live_share.IFollowModeState.html#followingUserId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.IFollowModeState\"},{\"kind\":1024,\"name\":\"isLocalValue\",\"url\":\"interfaces/_microsoft_live_share.IFollowModeState.html#isLocalValue\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.IFollowModeState\"},{\"kind\":1024,\"name\":\"otherUsersCount\",\"url\":\"interfaces/_microsoft_live_share.IFollowModeState.html#otherUsersCount\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.IFollowModeState\"},{\"kind\":1024,\"name\":\"type\",\"url\":\"interfaces/_microsoft_live_share.IFollowModeState.html#type\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.IFollowModeState\"},{\"kind\":1024,\"name\":\"value\",\"url\":\"interfaces/_microsoft_live_share.IFollowModeState.html#value\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.IFollowModeState\"},{\"kind\":256,\"name\":\"ILiveEvent\",\"url\":\"interfaces/_microsoft_live_share.ILiveEvent.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":1024,\"name\":\"clientId\",\"url\":\"interfaces/_microsoft_live_share.ILiveEvent.html#clientId\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.ILiveEvent\"},{\"kind\":1024,\"name\":\"data\",\"url\":\"interfaces/_microsoft_live_share.ILiveEvent.html#data\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ILiveEvent\"},{\"kind\":1024,\"name\":\"name\",\"url\":\"interfaces/_microsoft_live_share.ILiveEvent.html#name\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.ILiveEvent\"},{\"kind\":1024,\"name\":\"timestamp\",\"url\":\"interfaces/_microsoft_live_share.ILiveEvent.html#timestamp\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.ILiveEvent\"},{\"kind\":256,\"name\":\"ILiveEventEvents\",\"url\":\"interfaces/_microsoft_live_share.ILiveEventEvents.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":256,\"name\":\"ILiveFollowModeEvents\",\"url\":\"interfaces/_microsoft_live_share.ILiveFollowModeEvents.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":256,\"name\":\"ILivePresenceEvents\",\"url\":\"interfaces/_microsoft_live_share.ILivePresenceEvents.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":256,\"name\":\"ILiveShareClientOptions\",\"url\":\"interfaces/_microsoft_live_share.ILiveShareClientOptions.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":1024,\"name\":\"canSendBackgroundUpdates\",\"url\":\"interfaces/_microsoft_live_share.ILiveShareClientOptions.html#canSendBackgroundUpdates\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ILiveShareClientOptions\"},{\"kind\":1024,\"name\":\"connection\",\"url\":\"interfaces/_microsoft_live_share.ILiveShareClientOptions.html#connection\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ILiveShareClientOptions\"},{\"kind\":1024,\"name\":\"logger\",\"url\":\"interfaces/_microsoft_live_share.ILiveShareClientOptions.html#logger\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ILiveShareClientOptions\"},{\"kind\":1024,\"name\":\"roleVerifier\",\"url\":\"interfaces/_microsoft_live_share.ILiveShareClientOptions.html#roleVerifier\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ILiveShareClientOptions\"},{\"kind\":1024,\"name\":\"timestampProvider\",\"url\":\"interfaces/_microsoft_live_share.ILiveShareClientOptions.html#timestampProvider\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ILiveShareClientOptions\"},{\"kind\":256,\"name\":\"ILiveShareHost\",\"url\":\"interfaces/_microsoft_live_share.ILiveShareHost.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":2048,\"name\":\"getClientInfo\",\"url\":\"interfaces/_microsoft_live_share.ILiveShareHost.html#getClientInfo\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ILiveShareHost\"},{\"kind\":2048,\"name\":\"getClientRoles\",\"url\":\"interfaces/_microsoft_live_share.ILiveShareHost.html#getClientRoles\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ILiveShareHost\"},{\"kind\":2048,\"name\":\"getFluidContainerId\",\"url\":\"interfaces/_microsoft_live_share.ILiveShareHost.html#getFluidContainerId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ILiveShareHost\"},{\"kind\":2048,\"name\":\"getFluidTenantInfo\",\"url\":\"interfaces/_microsoft_live_share.ILiveShareHost.html#getFluidTenantInfo\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ILiveShareHost\"},{\"kind\":2048,\"name\":\"getFluidToken\",\"url\":\"interfaces/_microsoft_live_share.ILiveShareHost.html#getFluidToken\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ILiveShareHost\"},{\"kind\":2048,\"name\":\"getNtpTime\",\"url\":\"interfaces/_microsoft_live_share.ILiveShareHost.html#getNtpTime\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ILiveShareHost\"},{\"kind\":2048,\"name\":\"registerClientId\",\"url\":\"interfaces/_microsoft_live_share.ILiveShareHost.html#registerClientId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ILiveShareHost\"},{\"kind\":2048,\"name\":\"setFluidContainerId\",\"url\":\"interfaces/_microsoft_live_share.ILiveShareHost.html#setFluidContainerId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ILiveShareHost\"},{\"kind\":256,\"name\":\"ILiveShareJoinResults\",\"url\":\"interfaces/_microsoft_live_share.ILiveShareJoinResults.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":1024,\"name\":\"container\",\"url\":\"interfaces/_microsoft_live_share.ILiveShareJoinResults.html#container\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ILiveShareJoinResults\"},{\"kind\":1024,\"name\":\"created\",\"url\":\"interfaces/_microsoft_live_share.ILiveShareJoinResults.html#created\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ILiveShareJoinResults\"},{\"kind\":1024,\"name\":\"services\",\"url\":\"interfaces/_microsoft_live_share.ILiveShareJoinResults.html#services\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ILiveShareJoinResults\"},{\"kind\":1024,\"name\":\"timestampProvider\",\"url\":\"interfaces/_microsoft_live_share.ILiveShareJoinResults.html#timestampProvider\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ILiveShareJoinResults\"},{\"kind\":256,\"name\":\"ILiveStateEvents\",\"url\":\"interfaces/_microsoft_live_share.ILiveStateEvents.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":256,\"name\":\"ILiveTelemetryProperties\",\"url\":\"interfaces/_microsoft_live_share.ILiveTelemetryProperties.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":1024,\"name\":\"clientId\",\"url\":\"interfaces/_microsoft_live_share.ILiveTelemetryProperties.html#clientId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ILiveTelemetryProperties\"},{\"kind\":1024,\"name\":\"correlationId\",\"url\":\"interfaces/_microsoft_live_share.ILiveTelemetryProperties.html#correlationId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ILiveTelemetryProperties\"},{\"kind\":1024,\"name\":\"eventName\",\"url\":\"interfaces/_microsoft_live_share.ILiveTelemetryProperties.html#eventName\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ILiveTelemetryProperties\"},{\"kind\":1024,\"name\":\"timestamp\",\"url\":\"interfaces/_microsoft_live_share.ILiveTelemetryProperties.html#timestamp\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ILiveTelemetryProperties\"},{\"kind\":256,\"name\":\"ILiveTimerEvents\",\"url\":\"interfaces/_microsoft_live_share.ILiveTimerEvents.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":256,\"name\":\"INtpTimeInfo\",\"url\":\"interfaces/_microsoft_live_share.INtpTimeInfo.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":1024,\"name\":\"ntpTime\",\"url\":\"interfaces/_microsoft_live_share.INtpTimeInfo.html#ntpTime\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.INtpTimeInfo\"},{\"kind\":1024,\"name\":\"ntpTimeInUTC\",\"url\":\"interfaces/_microsoft_live_share.INtpTimeInfo.html#ntpTimeInUTC\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.INtpTimeInfo\"},{\"kind\":256,\"name\":\"IRuntimeSignaler\",\"url\":\"interfaces/_microsoft_live_share.IRuntimeSignaler.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":1024,\"name\":\"clientId\",\"url\":\"interfaces/_microsoft_live_share.IRuntimeSignaler.html#clientId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.IRuntimeSignaler\"},{\"kind\":1024,\"name\":\"connected\",\"url\":\"interfaces/_microsoft_live_share.IRuntimeSignaler.html#connected\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.IRuntimeSignaler\"},{\"kind\":1024,\"name\":\"logger\",\"url\":\"interfaces/_microsoft_live_share.IRuntimeSignaler.html#logger\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.IRuntimeSignaler\"},{\"kind\":2048,\"name\":\"off\",\"url\":\"interfaces/_microsoft_live_share.IRuntimeSignaler.html#off\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.IRuntimeSignaler\"},{\"kind\":2048,\"name\":\"on\",\"url\":\"interfaces/_microsoft_live_share.IRuntimeSignaler.html#on\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.IRuntimeSignaler\"},{\"kind\":2048,\"name\":\"submitSignal\",\"url\":\"interfaces/_microsoft_live_share.IRuntimeSignaler.html#submitSignal\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.IRuntimeSignaler\"},{\"kind\":256,\"name\":\"ITimerConfig\",\"url\":\"interfaces/_microsoft_live_share.ITimerConfig.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":1024,\"name\":\"clientId\",\"url\":\"interfaces/_microsoft_live_share.ITimerConfig.html#clientId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ITimerConfig\"},{\"kind\":1024,\"name\":\"configChangedAt\",\"url\":\"interfaces/_microsoft_live_share.ITimerConfig.html#configChangedAt\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ITimerConfig\"},{\"kind\":1024,\"name\":\"duration\",\"url\":\"interfaces/_microsoft_live_share.ITimerConfig.html#duration\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.ITimerConfig\"},{\"kind\":1024,\"name\":\"position\",\"url\":\"interfaces/_microsoft_live_share.ITimerConfig.html#position\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.ITimerConfig\"},{\"kind\":1024,\"name\":\"running\",\"url\":\"interfaces/_microsoft_live_share.ITimerConfig.html#running\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share.ITimerConfig\"},{\"kind\":256,\"name\":\"ITimerConfigData\",\"url\":\"interfaces/_microsoft_live_share.ITimerConfigData.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":1024,\"name\":\"duration\",\"url\":\"interfaces/_microsoft_live_share.ITimerConfigData.html#duration\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ITimerConfigData\"},{\"kind\":1024,\"name\":\"position\",\"url\":\"interfaces/_microsoft_live_share.ITimerConfigData.html#position\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ITimerConfigData\"},{\"kind\":1024,\"name\":\"running\",\"url\":\"interfaces/_microsoft_live_share.ITimerConfigData.html#running\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.ITimerConfigData\"},{\"kind\":4194304,\"name\":\"FollowModePresenceUser\",\"url\":\"types/_microsoft_live_share.FollowModePresenceUser.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":4194304,\"name\":\"GetLocalUserCanSend\",\"url\":\"types/_microsoft_live_share.GetLocalUserCanSend.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/_microsoft_live_share.GetLocalUserCanSend.html#__type\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.GetLocalUserCanSend\"},{\"kind\":4194304,\"name\":\"LiveEventListener\",\"url\":\"types/_microsoft_live_share.LiveEventListener.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/_microsoft_live_share.LiveEventListener.html#__type\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.LiveEventListener\"},{\"kind\":4194304,\"name\":\"UpdateSynchronizationState\",\"url\":\"types/_microsoft_live_share.UpdateSynchronizationState.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/_microsoft_live_share.UpdateSynchronizationState.html#__type\",\"classes\":\"\",\"parent\":\"_microsoft_live_share.UpdateSynchronizationState\"},{\"kind\":64,\"name\":\"getLiveShareContainerSchemaProxy\",\"url\":\"functions/_microsoft_live_share.getLiveShareContainerSchemaProxy.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share\"},{\"kind\":2,\"name\":\"_microsoft_live_share_media\",\"url\":\"modules/_microsoft_live_share_media.html\",\"classes\":\"\"},{\"kind\":8,\"name\":\"LimitLevelType\",\"url\":\"enums/_microsoft_live_share_media.LimitLevelType.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media\"},{\"kind\":16,\"name\":\"fixed\",\"url\":\"enums/_microsoft_live_share_media.LimitLevelType.html#fixed\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.LimitLevelType\"},{\"kind\":16,\"name\":\"percentage\",\"url\":\"enums/_microsoft_live_share_media.LimitLevelType.html#percentage\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.LimitLevelType\"},{\"kind\":8,\"name\":\"MediaPlayerSynchronizerEvents\",\"url\":\"enums/_microsoft_live_share_media.MediaPlayerSynchronizerEvents.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media\"},{\"kind\":16,\"name\":\"coordinatorstatechange\",\"url\":\"enums/_microsoft_live_share_media.MediaPlayerSynchronizerEvents.html#coordinatorstatechange\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.MediaPlayerSynchronizerEvents\"},{\"kind\":16,\"name\":\"groupaction\",\"url\":\"enums/_microsoft_live_share_media.MediaPlayerSynchronizerEvents.html#groupaction\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.MediaPlayerSynchronizerEvents\"},{\"kind\":16,\"name\":\"useraction\",\"url\":\"enums/_microsoft_live_share_media.MediaPlayerSynchronizerEvents.html#useraction\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.MediaPlayerSynchronizerEvents\"},{\"kind\":8,\"name\":\"MediaSessionCoordinatorEvents\",\"url\":\"enums/_microsoft_live_share_media.MediaSessionCoordinatorEvents.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media\"},{\"kind\":16,\"name\":\"coordinatorstatechange\",\"url\":\"enums/_microsoft_live_share_media.MediaSessionCoordinatorEvents.html#coordinatorstatechange\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.MediaSessionCoordinatorEvents\"},{\"kind\":16,\"name\":\"triggeraction\",\"url\":\"enums/_microsoft_live_share_media.MediaSessionCoordinatorEvents.html#triggeraction\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.MediaSessionCoordinatorEvents\"},{\"kind\":128,\"name\":\"LiveMediaSession\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSession.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSession.html#constructor\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_media.LiveMediaSession\"},{\"kind\":1024,\"name\":\"TypeName\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSession.html#TypeName\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.LiveMediaSession\"},{\"kind\":1024,\"name\":\"factory\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSession.html#factory\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.LiveMediaSession\"},{\"kind\":262144,\"name\":\"actionThrottler\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSession.html#actionThrottler\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.LiveMediaSession\"},{\"kind\":262144,\"name\":\"coordinator\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSession.html#coordinator\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.LiveMediaSession\"},{\"kind\":262144,\"name\":\"initializeState\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSession.html#initializeState\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_media.LiveMediaSession\"},{\"kind\":262144,\"name\":\"isInitialized\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSession.html#isInitialized\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_media.LiveMediaSession\"},{\"kind\":262144,\"name\":\"logger\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSession.html#logger\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.LiveMediaSession\"},{\"kind\":2048,\"name\":\"getClientInfo\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSession.html#getClientInfo\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_media.LiveMediaSession\"},{\"kind\":2048,\"name\":\"hasInitialized\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSession.html#hasInitialized\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_media.LiveMediaSession\"},{\"kind\":2048,\"name\":\"initialize\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSession.html#initialize\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.LiveMediaSession\"},{\"kind\":2048,\"name\":\"setActionHandler\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSession.html#setActionHandler\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.LiveMediaSession\"},{\"kind\":2048,\"name\":\"setRequestPlayerStateHandler\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSession.html#setRequestPlayerStateHandler\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.LiveMediaSession\"},{\"kind\":2048,\"name\":\"synchronize\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSession.html#synchronize\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.LiveMediaSession\"},{\"kind\":2048,\"name\":\"verifyLocalUserRoles\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSession.html#verifyLocalUserRoles\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_media.LiveMediaSession\"},{\"kind\":2048,\"name\":\"waitUntilConnected\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSession.html#waitUntilConnected\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_media.LiveMediaSession\"},{\"kind\":128,\"name\":\"LiveMediaSessionCoordinator\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSessionCoordinator.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media\"},{\"kind\":1024,\"name\":\"canPlayPause\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSessionCoordinator.html#canPlayPause\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.LiveMediaSessionCoordinator\"},{\"kind\":1024,\"name\":\"canSeek\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSessionCoordinator.html#canSeek\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.LiveMediaSessionCoordinator\"},{\"kind\":1024,\"name\":\"canSendPositionUpdates\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSessionCoordinator.html#canSendPositionUpdates\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.LiveMediaSessionCoordinator\"},{\"kind\":1024,\"name\":\"canSetTrack\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSessionCoordinator.html#canSetTrack\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.LiveMediaSessionCoordinator\"},{\"kind\":1024,\"name\":\"canSetTrackData\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSessionCoordinator.html#canSetTrackData\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.LiveMediaSessionCoordinator\"},{\"kind\":262144,\"name\":\"isSuspended\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSessionCoordinator.html#isSuspended\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.LiveMediaSessionCoordinator\"},{\"kind\":262144,\"name\":\"maxPlaybackDrift\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSessionCoordinator.html#maxPlaybackDrift\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.LiveMediaSessionCoordinator\"},{\"kind\":262144,\"name\":\"positionUpdateInterval\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSessionCoordinator.html#positionUpdateInterval\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.LiveMediaSessionCoordinator\"},{\"kind\":2048,\"name\":\"beginSuspension\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSessionCoordinator.html#beginSuspension\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.LiveMediaSessionCoordinator\"},{\"kind\":2048,\"name\":\"createChildren\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSessionCoordinator.html#createChildren\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_media.LiveMediaSessionCoordinator\"},{\"kind\":2048,\"name\":\"pause\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSessionCoordinator.html#pause\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.LiveMediaSessionCoordinator\"},{\"kind\":2048,\"name\":\"play\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSessionCoordinator.html#play\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.LiveMediaSessionCoordinator\"},{\"kind\":2048,\"name\":\"seekTo\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSessionCoordinator.html#seekTo\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.LiveMediaSessionCoordinator\"},{\"kind\":2048,\"name\":\"setTrack\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSessionCoordinator.html#setTrack\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.LiveMediaSessionCoordinator\"},{\"kind\":2048,\"name\":\"setTrackData\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSessionCoordinator.html#setTrackData\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.LiveMediaSessionCoordinator\"},{\"kind\":128,\"name\":\"LiveMediaSessionCoordinatorSuspension\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSessionCoordinatorSuspension.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSessionCoordinatorSuspension.html#constructor\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.LiveMediaSessionCoordinatorSuspension\"},{\"kind\":262144,\"name\":\"waitPoint\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSessionCoordinatorSuspension.html#waitPoint\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.LiveMediaSessionCoordinatorSuspension\"},{\"kind\":2048,\"name\":\"end\",\"url\":\"classes/_microsoft_live_share_media.LiveMediaSessionCoordinatorSuspension.html#end\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.LiveMediaSessionCoordinatorSuspension\"},{\"kind\":128,\"name\":\"MediaPlayerSynchronizer\",\"url\":\"classes/_microsoft_live_share_media.MediaPlayerSynchronizer.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share_media.MediaPlayerSynchronizer.html#constructor\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.MediaPlayerSynchronizer\"},{\"kind\":262144,\"name\":\"mediaSession\",\"url\":\"classes/_microsoft_live_share_media.MediaPlayerSynchronizer.html#mediaSession\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.MediaPlayerSynchronizer\"},{\"kind\":262144,\"name\":\"player\",\"url\":\"classes/_microsoft_live_share_media.MediaPlayerSynchronizer.html#player\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.MediaPlayerSynchronizer\"},{\"kind\":262144,\"name\":\"viewOnly\",\"url\":\"classes/_microsoft_live_share_media.MediaPlayerSynchronizer.html#viewOnly\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.MediaPlayerSynchronizer\"},{\"kind\":262144,\"name\":\"volumeManager\",\"url\":\"classes/_microsoft_live_share_media.MediaPlayerSynchronizer.html#volumeManager\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.MediaPlayerSynchronizer\"},{\"kind\":2048,\"name\":\"addEventListener\",\"url\":\"classes/_microsoft_live_share_media.MediaPlayerSynchronizer.html#addEventListener\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.MediaPlayerSynchronizer\"},{\"kind\":2048,\"name\":\"beginSeek\",\"url\":\"classes/_microsoft_live_share_media.MediaPlayerSynchronizer.html#beginSeek\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.MediaPlayerSynchronizer\"},{\"kind\":2048,\"name\":\"end\",\"url\":\"classes/_microsoft_live_share_media.MediaPlayerSynchronizer.html#end\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.MediaPlayerSynchronizer\"},{\"kind\":2048,\"name\":\"endSeek\",\"url\":\"classes/_microsoft_live_share_media.MediaPlayerSynchronizer.html#endSeek\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.MediaPlayerSynchronizer\"},{\"kind\":2048,\"name\":\"pause\",\"url\":\"classes/_microsoft_live_share_media.MediaPlayerSynchronizer.html#pause\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.MediaPlayerSynchronizer\"},{\"kind\":2048,\"name\":\"play\",\"url\":\"classes/_microsoft_live_share_media.MediaPlayerSynchronizer.html#play\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.MediaPlayerSynchronizer\"},{\"kind\":2048,\"name\":\"removeEventListener\",\"url\":\"classes/_microsoft_live_share_media.MediaPlayerSynchronizer.html#removeEventListener\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.MediaPlayerSynchronizer\"},{\"kind\":2048,\"name\":\"seekTo\",\"url\":\"classes/_microsoft_live_share_media.MediaPlayerSynchronizer.html#seekTo\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.MediaPlayerSynchronizer\"},{\"kind\":2048,\"name\":\"setTrack\",\"url\":\"classes/_microsoft_live_share_media.MediaPlayerSynchronizer.html#setTrack\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.MediaPlayerSynchronizer\"},{\"kind\":2048,\"name\":\"setTrackData\",\"url\":\"classes/_microsoft_live_share_media.MediaPlayerSynchronizer.html#setTrackData\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.MediaPlayerSynchronizer\"},{\"kind\":128,\"name\":\"MediaSessionActionThrottler\",\"url\":\"classes/_microsoft_live_share_media.MediaSessionActionThrottler.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share_media.MediaSessionActionThrottler.html#constructor\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.MediaSessionActionThrottler\"},{\"kind\":2048,\"name\":\"throttled\",\"url\":\"classes/_microsoft_live_share_media.MediaSessionActionThrottler.html#throttled\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.MediaSessionActionThrottler\"},{\"kind\":128,\"name\":\"RepeatedActionThrottler\",\"url\":\"classes/_microsoft_live_share_media.RepeatedActionThrottler.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share_media.RepeatedActionThrottler.html#constructor\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_media.RepeatedActionThrottler\"},{\"kind\":262144,\"name\":\"repeatInterval\",\"url\":\"classes/_microsoft_live_share_media.RepeatedActionThrottler.html#repeatInterval\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.RepeatedActionThrottler\"},{\"kind\":2048,\"name\":\"throttled\",\"url\":\"classes/_microsoft_live_share_media.RepeatedActionThrottler.html#throttled\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.RepeatedActionThrottler\"},{\"kind\":128,\"name\":\"VolumeManager\",\"url\":\"classes/_microsoft_live_share_media.VolumeManager.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share_media.VolumeManager.html#constructor\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.VolumeManager\"},{\"kind\":262144,\"name\":\"isLimiting\",\"url\":\"classes/_microsoft_live_share_media.VolumeManager.html#isLimiting\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.VolumeManager\"},{\"kind\":262144,\"name\":\"limitLevel\",\"url\":\"classes/_microsoft_live_share_media.VolumeManager.html#limitLevel\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.VolumeManager\"},{\"kind\":262144,\"name\":\"limitLevelType\",\"url\":\"classes/_microsoft_live_share_media.VolumeManager.html#limitLevelType\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.VolumeManager\"},{\"kind\":262144,\"name\":\"volume\",\"url\":\"classes/_microsoft_live_share_media.VolumeManager.html#volume\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.VolumeManager\"},{\"kind\":262144,\"name\":\"volumeChangeDuration\",\"url\":\"classes/_microsoft_live_share_media.VolumeManager.html#volumeChangeDuration\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.VolumeManager\"},{\"kind\":2048,\"name\":\"startLimiting\",\"url\":\"classes/_microsoft_live_share_media.VolumeManager.html#startLimiting\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.VolumeManager\"},{\"kind\":2048,\"name\":\"stopLimiting\",\"url\":\"classes/_microsoft_live_share_media.VolumeManager.html#stopLimiting\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.VolumeManager\"},{\"kind\":256,\"name\":\"CoordinationWaitPoint\",\"url\":\"interfaces/_microsoft_live_share_media.CoordinationWaitPoint.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media\"},{\"kind\":1024,\"name\":\"maxClients\",\"url\":\"interfaces/_microsoft_live_share_media.CoordinationWaitPoint.html#maxClients\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.CoordinationWaitPoint\"},{\"kind\":1024,\"name\":\"position\",\"url\":\"interfaces/_microsoft_live_share_media.CoordinationWaitPoint.html#position\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.CoordinationWaitPoint\"},{\"kind\":1024,\"name\":\"reason\",\"url\":\"interfaces/_microsoft_live_share_media.CoordinationWaitPoint.html#reason\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.CoordinationWaitPoint\"},{\"kind\":256,\"name\":\"ExtendedMediaMetadata\",\"url\":\"interfaces/_microsoft_live_share_media.ExtendedMediaMetadata.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media\"},{\"kind\":1024,\"name\":\"liveStream\",\"url\":\"interfaces/_microsoft_live_share_media.ExtendedMediaMetadata.html#liveStream\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.ExtendedMediaMetadata\"},{\"kind\":1024,\"name\":\"trackIdentifier\",\"url\":\"interfaces/_microsoft_live_share_media.ExtendedMediaMetadata.html#trackIdentifier\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.ExtendedMediaMetadata\"},{\"kind\":256,\"name\":\"ExtendedMediaSessionActionDetails\",\"url\":\"interfaces/_microsoft_live_share_media.ExtendedMediaSessionActionDetails.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media\"},{\"kind\":1024,\"name\":\"action\",\"url\":\"interfaces/_microsoft_live_share_media.ExtendedMediaSessionActionDetails.html#action\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.ExtendedMediaSessionActionDetails\"},{\"kind\":1024,\"name\":\"blocked\",\"url\":\"interfaces/_microsoft_live_share_media.ExtendedMediaSessionActionDetails.html#blocked\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.ExtendedMediaSessionActionDetails\"},{\"kind\":1024,\"name\":\"clientId\",\"url\":\"interfaces/_microsoft_live_share_media.ExtendedMediaSessionActionDetails.html#clientId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.ExtendedMediaSessionActionDetails\"},{\"kind\":1024,\"name\":\"data\",\"url\":\"interfaces/_microsoft_live_share_media.ExtendedMediaSessionActionDetails.html#data\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.ExtendedMediaSessionActionDetails\"},{\"kind\":1024,\"name\":\"fastSeek\",\"url\":\"interfaces/_microsoft_live_share_media.ExtendedMediaSessionActionDetails.html#fastSeek\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.ExtendedMediaSessionActionDetails\"},{\"kind\":1024,\"name\":\"local\",\"url\":\"interfaces/_microsoft_live_share_media.ExtendedMediaSessionActionDetails.html#local\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.ExtendedMediaSessionActionDetails\"},{\"kind\":1024,\"name\":\"metadata\",\"url\":\"interfaces/_microsoft_live_share_media.ExtendedMediaSessionActionDetails.html#metadata\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.ExtendedMediaSessionActionDetails\"},{\"kind\":1024,\"name\":\"seekOffset\",\"url\":\"interfaces/_microsoft_live_share_media.ExtendedMediaSessionActionDetails.html#seekOffset\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.ExtendedMediaSessionActionDetails\"},{\"kind\":1024,\"name\":\"seekTime\",\"url\":\"interfaces/_microsoft_live_share_media.ExtendedMediaSessionActionDetails.html#seekTime\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.ExtendedMediaSessionActionDetails\"},{\"kind\":1024,\"name\":\"source\",\"url\":\"interfaces/_microsoft_live_share_media.ExtendedMediaSessionActionDetails.html#source\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.ExtendedMediaSessionActionDetails\"},{\"kind\":1024,\"name\":\"suspension\",\"url\":\"interfaces/_microsoft_live_share_media.ExtendedMediaSessionActionDetails.html#suspension\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.ExtendedMediaSessionActionDetails\"},{\"kind\":256,\"name\":\"ExtendedMediaSessionActionHandler\",\"url\":\"interfaces/_microsoft_live_share_media.ExtendedMediaSessionActionHandler.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media\"},{\"kind\":256,\"name\":\"IMediaPlayer\",\"url\":\"interfaces/_microsoft_live_share_media.IMediaPlayer.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media\"},{\"kind\":1024,\"name\":\"currentSrc\",\"url\":\"interfaces/_microsoft_live_share_media.IMediaPlayer.html#currentSrc\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.IMediaPlayer\"},{\"kind\":1024,\"name\":\"currentTime\",\"url\":\"interfaces/_microsoft_live_share_media.IMediaPlayer.html#currentTime\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.IMediaPlayer\"},{\"kind\":1024,\"name\":\"duration\",\"url\":\"interfaces/_microsoft_live_share_media.IMediaPlayer.html#duration\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.IMediaPlayer\"},{\"kind\":1024,\"name\":\"ended\",\"url\":\"interfaces/_microsoft_live_share_media.IMediaPlayer.html#ended\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.IMediaPlayer\"},{\"kind\":1024,\"name\":\"muted\",\"url\":\"interfaces/_microsoft_live_share_media.IMediaPlayer.html#muted\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.IMediaPlayer\"},{\"kind\":1024,\"name\":\"paused\",\"url\":\"interfaces/_microsoft_live_share_media.IMediaPlayer.html#paused\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.IMediaPlayer\"},{\"kind\":1024,\"name\":\"playbackRate\",\"url\":\"interfaces/_microsoft_live_share_media.IMediaPlayer.html#playbackRate\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.IMediaPlayer\"},{\"kind\":1024,\"name\":\"src\",\"url\":\"interfaces/_microsoft_live_share_media.IMediaPlayer.html#src\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.IMediaPlayer\"},{\"kind\":1024,\"name\":\"volume\",\"url\":\"interfaces/_microsoft_live_share_media.IMediaPlayer.html#volume\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.IMediaPlayer\"},{\"kind\":2048,\"name\":\"addEventListener\",\"url\":\"interfaces/_microsoft_live_share_media.IMediaPlayer.html#addEventListener\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.IMediaPlayer\"},{\"kind\":2048,\"name\":\"load\",\"url\":\"interfaces/_microsoft_live_share_media.IMediaPlayer.html#load\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.IMediaPlayer\"},{\"kind\":2048,\"name\":\"pause\",\"url\":\"interfaces/_microsoft_live_share_media.IMediaPlayer.html#pause\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.IMediaPlayer\"},{\"kind\":2048,\"name\":\"play\",\"url\":\"interfaces/_microsoft_live_share_media.IMediaPlayer.html#play\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.IMediaPlayer\"},{\"kind\":2048,\"name\":\"removeEventListener\",\"url\":\"interfaces/_microsoft_live_share_media.IMediaPlayer.html#removeEventListener\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.IMediaPlayer\"},{\"kind\":256,\"name\":\"IMediaPlayerState\",\"url\":\"interfaces/_microsoft_live_share_media.IMediaPlayerState.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media\"},{\"kind\":1024,\"name\":\"metadata\",\"url\":\"interfaces/_microsoft_live_share_media.IMediaPlayerState.html#metadata\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.IMediaPlayerState\"},{\"kind\":1024,\"name\":\"playbackState\",\"url\":\"interfaces/_microsoft_live_share_media.IMediaPlayerState.html#playbackState\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.IMediaPlayerState\"},{\"kind\":1024,\"name\":\"positionState\",\"url\":\"interfaces/_microsoft_live_share_media.IMediaPlayerState.html#positionState\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.IMediaPlayerState\"},{\"kind\":1024,\"name\":\"trackData\",\"url\":\"interfaces/_microsoft_live_share_media.IMediaPlayerState.html#trackData\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.IMediaPlayerState\"},{\"kind\":256,\"name\":\"IMediaPlayerSynchronizerEvent\",\"url\":\"interfaces/_microsoft_live_share_media.IMediaPlayerSynchronizerEvent.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media\"},{\"kind\":1024,\"name\":\"clientId\",\"url\":\"interfaces/_microsoft_live_share_media.IMediaPlayerSynchronizerEvent.html#clientId\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_media.IMediaPlayerSynchronizerEvent\"},{\"kind\":1024,\"name\":\"data\",\"url\":\"interfaces/_microsoft_live_share_media.IMediaPlayerSynchronizerEvent.html#data\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_media.IMediaPlayerSynchronizerEvent\"},{\"kind\":1024,\"name\":\"details\",\"url\":\"interfaces/_microsoft_live_share_media.IMediaPlayerSynchronizerEvent.html#details\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.IMediaPlayerSynchronizerEvent\"},{\"kind\":1024,\"name\":\"error\",\"url\":\"interfaces/_microsoft_live_share_media.IMediaPlayerSynchronizerEvent.html#error\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.IMediaPlayerSynchronizerEvent\"},{\"kind\":1024,\"name\":\"name\",\"url\":\"interfaces/_microsoft_live_share_media.IMediaPlayerSynchronizerEvent.html#name\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_media.IMediaPlayerSynchronizerEvent\"},{\"kind\":1024,\"name\":\"timestamp\",\"url\":\"interfaces/_microsoft_live_share_media.IMediaPlayerSynchronizerEvent.html#timestamp\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_media.IMediaPlayerSynchronizerEvent\"},{\"kind\":256,\"name\":\"MediaSessionCoordinatorSuspension\",\"url\":\"interfaces/_microsoft_live_share_media.MediaSessionCoordinatorSuspension.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media\"},{\"kind\":1024,\"name\":\"waitPoint\",\"url\":\"interfaces/_microsoft_live_share_media.MediaSessionCoordinatorSuspension.html#waitPoint\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.MediaSessionCoordinatorSuspension\"},{\"kind\":2048,\"name\":\"end\",\"url\":\"interfaces/_microsoft_live_share_media.MediaSessionCoordinatorSuspension.html#end\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media.MediaSessionCoordinatorSuspension\"},{\"kind\":4194304,\"name\":\"ExtendedMediaSessionAction\",\"url\":\"types/_microsoft_live_share_media.ExtendedMediaSessionAction.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media\"},{\"kind\":4194304,\"name\":\"ExtendedMediaSessionActionSource\",\"url\":\"types/_microsoft_live_share_media.ExtendedMediaSessionActionSource.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media\"},{\"kind\":4194304,\"name\":\"ExtendedMediaSessionPlaybackState\",\"url\":\"types/_microsoft_live_share_media.ExtendedMediaSessionPlaybackState.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media\"},{\"kind\":4194304,\"name\":\"MediaSessionCoordinatorState\",\"url\":\"types/_microsoft_live_share_media.MediaSessionCoordinatorState.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_media\"},{\"kind\":2,\"name\":\"_microsoft_live_share_turbo\",\"url\":\"modules/_microsoft_live_share_turbo.html\",\"classes\":\"\"},{\"kind\":128,\"name\":\"AzureTurboClient\",\"url\":\"classes/_microsoft_live_share_turbo.AzureTurboClient.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share_turbo.AzureTurboClient.html#constructor\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.AzureTurboClient\"},{\"kind\":262144,\"name\":\"canSendBackgroundUpdates\",\"url\":\"classes/_microsoft_live_share_turbo.AzureTurboClient.html#canSendBackgroundUpdates\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.AzureTurboClient\"},{\"kind\":262144,\"name\":\"results\",\"url\":\"classes/_microsoft_live_share_turbo.AzureTurboClient.html#results\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.AzureTurboClient\"},{\"kind\":262144,\"name\":\"stateMap\",\"url\":\"classes/_microsoft_live_share_turbo.AzureTurboClient.html#stateMap\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_turbo.AzureTurboClient\"},{\"kind\":2048,\"name\":\"createContainer\",\"url\":\"classes/_microsoft_live_share_turbo.AzureTurboClient.html#createContainer\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.AzureTurboClient\"},{\"kind\":2048,\"name\":\"getContainer\",\"url\":\"classes/_microsoft_live_share_turbo.AzureTurboClient.html#getContainer\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.AzureTurboClient\"},{\"kind\":2048,\"name\":\"getContainerSchema\",\"url\":\"classes/_microsoft_live_share_turbo.AzureTurboClient.html#getContainerSchema\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_turbo.AzureTurboClient\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/_microsoft_live_share_turbo.AzureTurboClient.html#getContainerSchema.getContainerSchema-1.__type\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.AzureTurboClient.getContainerSchema.getContainerSchema\"},{\"kind\":1024,\"name\":\"dynamicObjectTypes\",\"url\":\"classes/_microsoft_live_share_turbo.AzureTurboClient.html#getContainerSchema.getContainerSchema-1.__type.dynamicObjectTypes\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.AzureTurboClient.getContainerSchema.getContainerSchema.__type\"},{\"kind\":1024,\"name\":\"initialObjects\",\"url\":\"classes/_microsoft_live_share_turbo.AzureTurboClient.html#getContainerSchema.getContainerSchema-1.__type.initialObjects\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.AzureTurboClient.getContainerSchema.getContainerSchema.__type\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/_microsoft_live_share_turbo.AzureTurboClient.html#getContainerSchema.getContainerSchema-1.__type.initialObjects.__type-1\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.AzureTurboClient.getContainerSchema.getContainerSchema.__type.initialObjects\"},{\"kind\":2048,\"name\":\"getDDS\",\"url\":\"classes/_microsoft_live_share_turbo.AzureTurboClient.html#getDDS\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_turbo.AzureTurboClient\"},{\"kind\":128,\"name\":\"DynamicObjectManager\",\"url\":\"classes/_microsoft_live_share_turbo.DynamicObjectManager.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share_turbo.DynamicObjectManager.html#constructor\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_turbo.DynamicObjectManager\"},{\"kind\":1024,\"name\":\"TypeName\",\"url\":\"classes/_microsoft_live_share_turbo.DynamicObjectManager.html#TypeName\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.DynamicObjectManager\"},{\"kind\":1024,\"name\":\"factory\",\"url\":\"classes/_microsoft_live_share_turbo.DynamicObjectManager.html#factory\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.DynamicObjectManager\"},{\"kind\":262144,\"name\":\"initializeState\",\"url\":\"classes/_microsoft_live_share_turbo.DynamicObjectManager.html#initializeState\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_turbo.DynamicObjectManager\"},{\"kind\":262144,\"name\":\"isInitialized\",\"url\":\"classes/_microsoft_live_share_turbo.DynamicObjectManager.html#isInitialized\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_turbo.DynamicObjectManager\"},{\"kind\":2048,\"name\":\"getClientInfo\",\"url\":\"classes/_microsoft_live_share_turbo.DynamicObjectManager.html#getClientInfo\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_turbo.DynamicObjectManager\"},{\"kind\":2048,\"name\":\"getDDS\",\"url\":\"classes/_microsoft_live_share_turbo.DynamicObjectManager.html#getDDS\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.DynamicObjectManager\"},{\"kind\":2048,\"name\":\"hasInitialized\",\"url\":\"classes/_microsoft_live_share_turbo.DynamicObjectManager.html#hasInitialized\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_turbo.DynamicObjectManager\"},{\"kind\":2048,\"name\":\"initializingFirstTime\",\"url\":\"classes/_microsoft_live_share_turbo.DynamicObjectManager.html#initializingFirstTime\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_turbo.DynamicObjectManager\"},{\"kind\":2048,\"name\":\"verifyLocalUserRoles\",\"url\":\"classes/_microsoft_live_share_turbo.DynamicObjectManager.html#verifyLocalUserRoles\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_turbo.DynamicObjectManager\"},{\"kind\":2048,\"name\":\"waitUntilConnected\",\"url\":\"classes/_microsoft_live_share_turbo.DynamicObjectManager.html#waitUntilConnected\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_turbo.DynamicObjectManager\"},{\"kind\":128,\"name\":\"FluidTurboClient\",\"url\":\"classes/_microsoft_live_share_turbo.FluidTurboClient.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share_turbo.FluidTurboClient.html#constructor\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.FluidTurboClient\"},{\"kind\":262144,\"name\":\"canSendBackgroundUpdates\",\"url\":\"classes/_microsoft_live_share_turbo.FluidTurboClient.html#canSendBackgroundUpdates\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.FluidTurboClient\"},{\"kind\":262144,\"name\":\"results\",\"url\":\"classes/_microsoft_live_share_turbo.FluidTurboClient.html#results\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.FluidTurboClient\"},{\"kind\":262144,\"name\":\"stateMap\",\"url\":\"classes/_microsoft_live_share_turbo.FluidTurboClient.html#stateMap\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.FluidTurboClient\"},{\"kind\":2048,\"name\":\"getContainerSchema\",\"url\":\"classes/_microsoft_live_share_turbo.FluidTurboClient.html#getContainerSchema\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_turbo.FluidTurboClient\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/_microsoft_live_share_turbo.FluidTurboClient.html#getContainerSchema.getContainerSchema-1.__type\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.FluidTurboClient.getContainerSchema.getContainerSchema\"},{\"kind\":1024,\"name\":\"dynamicObjectTypes\",\"url\":\"classes/_microsoft_live_share_turbo.FluidTurboClient.html#getContainerSchema.getContainerSchema-1.__type.dynamicObjectTypes\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.FluidTurboClient.getContainerSchema.getContainerSchema.__type\"},{\"kind\":1024,\"name\":\"initialObjects\",\"url\":\"classes/_microsoft_live_share_turbo.FluidTurboClient.html#getContainerSchema.getContainerSchema-1.__type.initialObjects\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.FluidTurboClient.getContainerSchema.getContainerSchema.__type\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/_microsoft_live_share_turbo.FluidTurboClient.html#getContainerSchema.getContainerSchema-1.__type.initialObjects.__type-1\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.FluidTurboClient.getContainerSchema.getContainerSchema.__type.initialObjects\"},{\"kind\":2048,\"name\":\"getDDS\",\"url\":\"classes/_microsoft_live_share_turbo.FluidTurboClient.html#getDDS\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.FluidTurboClient\"},{\"kind\":128,\"name\":\"LiveShareTurboClient\",\"url\":\"classes/_microsoft_live_share_turbo.LiveShareTurboClient.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share_turbo.LiveShareTurboClient.html#constructor\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.LiveShareTurboClient\"},{\"kind\":262144,\"name\":\"canSendBackgroundUpdates\",\"url\":\"classes/_microsoft_live_share_turbo.LiveShareTurboClient.html#canSendBackgroundUpdates\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.LiveShareTurboClient\"},{\"kind\":262144,\"name\":\"isTesting\",\"url\":\"classes/_microsoft_live_share_turbo.LiveShareTurboClient.html#isTesting\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.LiveShareTurboClient\"},{\"kind\":262144,\"name\":\"maxContainerLookupTries\",\"url\":\"classes/_microsoft_live_share_turbo.LiveShareTurboClient.html#maxContainerLookupTries\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.LiveShareTurboClient\"},{\"kind\":262144,\"name\":\"results\",\"url\":\"classes/_microsoft_live_share_turbo.LiveShareTurboClient.html#results\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.LiveShareTurboClient\"},{\"kind\":262144,\"name\":\"stateMap\",\"url\":\"classes/_microsoft_live_share_turbo.LiveShareTurboClient.html#stateMap\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_turbo.LiveShareTurboClient\"},{\"kind\":2048,\"name\":\"getContainerSchema\",\"url\":\"classes/_microsoft_live_share_turbo.LiveShareTurboClient.html#getContainerSchema\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_turbo.LiveShareTurboClient\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/_microsoft_live_share_turbo.LiveShareTurboClient.html#getContainerSchema.getContainerSchema-1.__type\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.LiveShareTurboClient.getContainerSchema.getContainerSchema\"},{\"kind\":1024,\"name\":\"dynamicObjectTypes\",\"url\":\"classes/_microsoft_live_share_turbo.LiveShareTurboClient.html#getContainerSchema.getContainerSchema-1.__type.dynamicObjectTypes\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.LiveShareTurboClient.getContainerSchema.getContainerSchema.__type\"},{\"kind\":1024,\"name\":\"initialObjects\",\"url\":\"classes/_microsoft_live_share_turbo.LiveShareTurboClient.html#getContainerSchema.getContainerSchema-1.__type.initialObjects\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.LiveShareTurboClient.getContainerSchema.getContainerSchema.__type\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/_microsoft_live_share_turbo.LiveShareTurboClient.html#getContainerSchema.getContainerSchema-1.__type.initialObjects.__type-1\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.LiveShareTurboClient.getContainerSchema.getContainerSchema.__type.initialObjects\"},{\"kind\":2048,\"name\":\"getDDS\",\"url\":\"classes/_microsoft_live_share_turbo.LiveShareTurboClient.html#getDDS\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_turbo.LiveShareTurboClient\"},{\"kind\":2048,\"name\":\"join\",\"url\":\"classes/_microsoft_live_share_turbo.LiveShareTurboClient.html#join\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.LiveShareTurboClient\"},{\"kind\":256,\"name\":\"IFluidTurboClient\",\"url\":\"interfaces/_microsoft_live_share_turbo.IFluidTurboClient.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo\"},{\"kind\":262144,\"name\":\"canSendBackgroundUpdates\",\"url\":\"interfaces/_microsoft_live_share_turbo.IFluidTurboClient.html#canSendBackgroundUpdates\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.IFluidTurboClient\"},{\"kind\":262144,\"name\":\"stateMap\",\"url\":\"interfaces/_microsoft_live_share_turbo.IFluidTurboClient.html#stateMap\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.IFluidTurboClient\"},{\"kind\":2048,\"name\":\"getDDS\",\"url\":\"interfaces/_microsoft_live_share_turbo.IFluidTurboClient.html#getDDS\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_turbo.IFluidTurboClient\"},{\"kind\":2,\"name\":\"_microsoft_live_share_canvas\",\"url\":\"modules/_microsoft_live_share_canvas.html\",\"classes\":\"\"},{\"kind\":8,\"name\":\"InkingTool\",\"url\":\"enums/_microsoft_live_share_canvas.InkingTool.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":16,\"name\":\"eraser\",\"url\":\"enums/_microsoft_live_share_canvas.InkingTool.html#eraser\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingTool\"},{\"kind\":16,\"name\":\"highlighter\",\"url\":\"enums/_microsoft_live_share_canvas.InkingTool.html#highlighter\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingTool\"},{\"kind\":16,\"name\":\"laserPointer\",\"url\":\"enums/_microsoft_live_share_canvas.InkingTool.html#laserPointer\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingTool\"},{\"kind\":16,\"name\":\"line\",\"url\":\"enums/_microsoft_live_share_canvas.InkingTool.html#line\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingTool\"},{\"kind\":16,\"name\":\"pen\",\"url\":\"enums/_microsoft_live_share_canvas.InkingTool.html#pen\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingTool\"},{\"kind\":16,\"name\":\"pointEraser\",\"url\":\"enums/_microsoft_live_share_canvas.InkingTool.html#pointEraser\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingTool\"},{\"kind\":8,\"name\":\"StrokeEndState\",\"url\":\"enums/_microsoft_live_share_canvas.StrokeEndState.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":16,\"name\":\"cancelled\",\"url\":\"enums/_microsoft_live_share_canvas.StrokeEndState.html#cancelled\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.StrokeEndState\"},{\"kind\":16,\"name\":\"ended\",\"url\":\"enums/_microsoft_live_share_canvas.StrokeEndState.html#ended\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.StrokeEndState\"},{\"kind\":8,\"name\":\"StrokeMode\",\"url\":\"enums/_microsoft_live_share_canvas.StrokeMode.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":16,\"name\":\"freeHand\",\"url\":\"enums/_microsoft_live_share_canvas.StrokeMode.html#freeHand\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.StrokeMode\"},{\"kind\":16,\"name\":\"line\",\"url\":\"enums/_microsoft_live_share_canvas.StrokeMode.html#line\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.StrokeMode\"},{\"kind\":8,\"name\":\"StrokeType\",\"url\":\"enums/_microsoft_live_share_canvas.StrokeType.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":16,\"name\":\"ephemeral\",\"url\":\"enums/_microsoft_live_share_canvas.StrokeType.html#ephemeral\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.StrokeType\"},{\"kind\":16,\"name\":\"laserPointer\",\"url\":\"enums/_microsoft_live_share_canvas.StrokeType.html#laserPointer\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.StrokeType\"},{\"kind\":16,\"name\":\"persistent\",\"url\":\"enums/_microsoft_live_share_canvas.StrokeType.html#persistent\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.StrokeType\"},{\"kind\":128,\"name\":\"DryCanvas\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#constructor\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":1024,\"name\":\"referencePoint\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#referencePoint\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":1024,\"name\":\"fadeOutDuration\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#fadeOutDuration\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":1024,\"name\":\"highlighterOpacity\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#highlighterOpacity\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":1024,\"name\":\"laserShadowOpacity\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#laserShadowOpacity\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":262144,\"name\":\"brush\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#brush\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":262144,\"name\":\"canvas\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#canvas\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":262144,\"name\":\"context\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#context\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":262144,\"name\":\"offset\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#offset\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":262144,\"name\":\"points\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#points\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":262144,\"name\":\"scale\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#scale\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"addLayer\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#addLayer\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"addPoint\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#addPoint\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"adjustOpacity\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#adjustOpacity\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"beginStroke\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#beginStroke\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"cancelStroke\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#cancelStroke\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"clear\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#clear\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"endStroke\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#endStroke\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"fadeOut\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#fadeOut\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"getBrushCssColor\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#getBrushCssColor\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"getDefaultBrush\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#getDefaultBrush\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"internalAddPoint\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#internalAddPoint\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"internalBeginStroke\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#internalBeginStroke\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"internalCancelStroke\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#internalCancelStroke\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"internalEndStroke\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#internalEndStroke\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"internalRender\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#internalRender\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"lineTo\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#lineTo\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"moveTo\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#moveTo\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"numsToIPointerPoint\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#numsToIPointerPoint\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"removeFromDOM\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#removeFromDOM\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"removeLayer\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#removeLayer\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"renderCircle\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#renderCircle\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"renderQuad\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#renderQuad\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"renderRectangle\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#renderRectangle\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"renderStroke\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#renderStroke\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"rendersAsynchronously\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#rendersAsynchronously\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"rendersProgressively\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#rendersProgressively\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"resize\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#resize\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"scheduleRender\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#scheduleRender\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"setBrush\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#setBrush\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":2048,\"name\":\"viewportToScreen\",\"url\":\"classes/_microsoft_live_share_canvas.DryCanvas.html#viewportToScreen\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryCanvas\"},{\"kind\":128,\"name\":\"DryWetCanvas\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#constructor\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":1024,\"name\":\"referencePoint\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#referencePoint\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":1024,\"name\":\"fadeOutDuration\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#fadeOutDuration\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":1024,\"name\":\"highlighterOpacity\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#highlighterOpacity\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":1024,\"name\":\"laserShadowOpacity\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#laserShadowOpacity\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":262144,\"name\":\"brush\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#brush\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":262144,\"name\":\"canvas\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#canvas\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":262144,\"name\":\"context\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#context\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":262144,\"name\":\"offset\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#offset\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":262144,\"name\":\"points\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#points\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":262144,\"name\":\"scale\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#scale\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"addLayer\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#addLayer\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"addPoint\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#addPoint\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"adjustOpacity\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#adjustOpacity\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"beginStroke\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#beginStroke\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"cancelStroke\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#cancelStroke\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"clear\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#clear\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"endStroke\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#endStroke\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"fadeOut\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#fadeOut\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"getBrushCssColor\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#getBrushCssColor\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"getDefaultBrush\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#getDefaultBrush\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"internalAddPoint\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#internalAddPoint\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"internalBeginStroke\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#internalBeginStroke\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"internalCancelStroke\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#internalCancelStroke\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"internalEndStroke\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#internalEndStroke\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"internalRender\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#internalRender\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"lineTo\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#lineTo\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"moveTo\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#moveTo\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"numsToIPointerPoint\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#numsToIPointerPoint\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"removeFromDOM\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#removeFromDOM\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"removeLayer\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#removeLayer\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"renderCircle\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#renderCircle\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"renderQuad\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#renderQuad\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"renderRectangle\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#renderRectangle\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"renderStroke\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#renderStroke\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"rendersAsynchronously\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#rendersAsynchronously\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"rendersProgressively\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#rendersProgressively\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"resize\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#resize\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"scheduleRender\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#scheduleRender\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"setBrush\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#setBrush\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":2048,\"name\":\"viewportToScreen\",\"url\":\"classes/_microsoft_live_share_canvas.DryWetCanvas.html#viewportToScreen\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.DryWetCanvas\"},{\"kind\":128,\"name\":\"InkingCanvas\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#constructor\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":1024,\"name\":\"referencePoint\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#referencePoint\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":1024,\"name\":\"fadeOutDuration\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#fadeOutDuration\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":1024,\"name\":\"highlighterOpacity\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#highlighterOpacity\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":1024,\"name\":\"laserShadowOpacity\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#laserShadowOpacity\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":262144,\"name\":\"brush\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#brush\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":262144,\"name\":\"canvas\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#canvas\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":262144,\"name\":\"context\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#context\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":262144,\"name\":\"offset\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#offset\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":262144,\"name\":\"scale\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#scale\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":2048,\"name\":\"addLayer\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#addLayer\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":2048,\"name\":\"addPoint\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#addPoint\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":2048,\"name\":\"beginStroke\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#beginStroke\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":2048,\"name\":\"cancelStroke\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#cancelStroke\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":2048,\"name\":\"clear\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#clear\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":2048,\"name\":\"endStroke\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#endStroke\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":2048,\"name\":\"fadeOut\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#fadeOut\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":2048,\"name\":\"getDefaultBrush\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#getDefaultBrush\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":2048,\"name\":\"internalAddPoint\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#internalAddPoint\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":2048,\"name\":\"internalBeginStroke\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#internalBeginStroke\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":2048,\"name\":\"internalCancelStroke\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#internalCancelStroke\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":2048,\"name\":\"internalEndStroke\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#internalEndStroke\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":2048,\"name\":\"internalRender\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#internalRender\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":2048,\"name\":\"lineTo\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#lineTo\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":2048,\"name\":\"moveTo\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#moveTo\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":2048,\"name\":\"numsToIPointerPoint\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#numsToIPointerPoint\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":2048,\"name\":\"removeFromDOM\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#removeFromDOM\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":2048,\"name\":\"removeLayer\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#removeLayer\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":2048,\"name\":\"renderCircle\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#renderCircle\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":2048,\"name\":\"renderQuad\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#renderQuad\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":2048,\"name\":\"renderRectangle\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#renderRectangle\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":2048,\"name\":\"renderStroke\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#renderStroke\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":2048,\"name\":\"rendersAsynchronously\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#rendersAsynchronously\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":2048,\"name\":\"resize\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#resize\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":2048,\"name\":\"scheduleRender\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#scheduleRender\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":2048,\"name\":\"setBrush\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#setBrush\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":2048,\"name\":\"viewportToScreen\",\"url\":\"classes/_microsoft_live_share_canvas.InkingCanvas.html#viewportToScreen\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.InkingCanvas\"},{\"kind\":128,\"name\":\"InkingManager\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#constructor\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":1024,\"name\":\"eraserSize\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#eraserSize\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":1024,\"name\":\"enableStrokeModifierHotKeys\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#enableStrokeModifierHotKeys\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":1024,\"name\":\"ephemeralCanvasRemovalDelay\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#ephemeralCanvasRemovalDelay\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":1024,\"name\":\"localClientId\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#localClientId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":262144,\"name\":\"centerX\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#centerX\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":262144,\"name\":\"centerY\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#centerY\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":262144,\"name\":\"clientHeight\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#clientHeight\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":262144,\"name\":\"clientWidth\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#clientWidth\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":262144,\"name\":\"highlighterBrush\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#highlighterBrush\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":262144,\"name\":\"hostElement\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#hostElement\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":262144,\"name\":\"inputProvider\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#inputProvider\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":262144,\"name\":\"laserPointerBrush\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#laserPointerBrush\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":262144,\"name\":\"lineBrush\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#lineBrush\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":262144,\"name\":\"offset\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#offset\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":262144,\"name\":\"penBrush\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#penBrush\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":262144,\"name\":\"referencePoint\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#referencePoint\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":262144,\"name\":\"scale\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#scale\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":262144,\"name\":\"tool\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#tool\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":262144,\"name\":\"viewPort\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#viewPort\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":2048,\"name\":\"activate\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#activate\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":2048,\"name\":\"addStroke\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#addStroke\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":2048,\"name\":\"beginUpdate\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#beginUpdate\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":2048,\"name\":\"beginWetStroke\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#beginWetStroke\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":2048,\"name\":\"clear\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#clear\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":2048,\"name\":\"deactivate\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#deactivate\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":2048,\"name\":\"endUpdate\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#endUpdate\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":2048,\"name\":\"erase\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#erase\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":2048,\"name\":\"exportRaw\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#exportRaw\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":2048,\"name\":\"exportSVG\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#exportSVG\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":2048,\"name\":\"getStroke\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#getStroke\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":2048,\"name\":\"importRaw\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#importRaw\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":2048,\"name\":\"pointErase\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#pointErase\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":2048,\"name\":\"removeStroke\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#removeStroke\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":2048,\"name\":\"screenToViewport\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#screenToViewport\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":2048,\"name\":\"setInputFilters\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#setInputFilters\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":2048,\"name\":\"viewportToScreen\",\"url\":\"classes/_microsoft_live_share_canvas.InkingManager.html#viewportToScreen\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InkingManager\"},{\"kind\":128,\"name\":\"InputFilter\",\"url\":\"classes/_microsoft_live_share_canvas.InputFilter.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share_canvas.InputFilter.html#constructor\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InputFilter\"},{\"kind\":2048,\"name\":\"filterPoint\",\"url\":\"classes/_microsoft_live_share_canvas.InputFilter.html#filterPoint\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InputFilter\"},{\"kind\":2048,\"name\":\"reset\",\"url\":\"classes/_microsoft_live_share_canvas.InputFilter.html#reset\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InputFilter\"},{\"kind\":128,\"name\":\"InputFilterCollection\",\"url\":\"classes/_microsoft_live_share_canvas.InputFilterCollection.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share_canvas.InputFilterCollection.html#constructor\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InputFilterCollection\"},{\"kind\":2048,\"name\":\"addFilters\",\"url\":\"classes/_microsoft_live_share_canvas.InputFilterCollection.html#addFilters\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InputFilterCollection\"},{\"kind\":2048,\"name\":\"filterPoint\",\"url\":\"classes/_microsoft_live_share_canvas.InputFilterCollection.html#filterPoint\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InputFilterCollection\"},{\"kind\":2048,\"name\":\"reset\",\"url\":\"classes/_microsoft_live_share_canvas.InputFilterCollection.html#reset\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InputFilterCollection\"},{\"kind\":128,\"name\":\"InputProvider\",\"url\":\"classes/_microsoft_live_share_canvas.InputProvider.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share_canvas.InputProvider.html#constructor\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InputProvider\"},{\"kind\":1024,\"name\":\"pointerDownEvent\",\"url\":\"classes/_microsoft_live_share_canvas.InputProvider.html#pointerDownEvent\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.InputProvider\"},{\"kind\":1024,\"name\":\"pointerEnterEvent\",\"url\":\"classes/_microsoft_live_share_canvas.InputProvider.html#pointerEnterEvent\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.InputProvider\"},{\"kind\":1024,\"name\":\"pointerLeaveEvent\",\"url\":\"classes/_microsoft_live_share_canvas.InputProvider.html#pointerLeaveEvent\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.InputProvider\"},{\"kind\":1024,\"name\":\"pointerMoveEvent\",\"url\":\"classes/_microsoft_live_share_canvas.InputProvider.html#pointerMoveEvent\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.InputProvider\"},{\"kind\":1024,\"name\":\"pointerUpEvent\",\"url\":\"classes/_microsoft_live_share_canvas.InputProvider.html#pointerUpEvent\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.InputProvider\"},{\"kind\":262144,\"name\":\"isActive\",\"url\":\"classes/_microsoft_live_share_canvas.InputProvider.html#isActive\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InputProvider\"},{\"kind\":262144,\"name\":\"pointerDown\",\"url\":\"classes/_microsoft_live_share_canvas.InputProvider.html#pointerDown\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InputProvider\"},{\"kind\":262144,\"name\":\"pointerEnter\",\"url\":\"classes/_microsoft_live_share_canvas.InputProvider.html#pointerEnter\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InputProvider\"},{\"kind\":262144,\"name\":\"pointerLeave\",\"url\":\"classes/_microsoft_live_share_canvas.InputProvider.html#pointerLeave\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InputProvider\"},{\"kind\":262144,\"name\":\"pointerMove\",\"url\":\"classes/_microsoft_live_share_canvas.InputProvider.html#pointerMove\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InputProvider\"},{\"kind\":262144,\"name\":\"pointerUp\",\"url\":\"classes/_microsoft_live_share_canvas.InputProvider.html#pointerUp\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InputProvider\"},{\"kind\":2048,\"name\":\"activate\",\"url\":\"classes/_microsoft_live_share_canvas.InputProvider.html#activate\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InputProvider\"},{\"kind\":2048,\"name\":\"deactivate\",\"url\":\"classes/_microsoft_live_share_canvas.InputProvider.html#deactivate\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.InputProvider\"},{\"kind\":128,\"name\":\"JitterFilter\",\"url\":\"classes/_microsoft_live_share_canvas.JitterFilter.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share_canvas.JitterFilter.html#constructor\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.JitterFilter\"},{\"kind\":2048,\"name\":\"filterPoint\",\"url\":\"classes/_microsoft_live_share_canvas.JitterFilter.html#filterPoint\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.JitterFilter\"},{\"kind\":2048,\"name\":\"reset\",\"url\":\"classes/_microsoft_live_share_canvas.JitterFilter.html#reset\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.JitterFilter\"},{\"kind\":128,\"name\":\"LaserPointerCanvas\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#constructor\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":1024,\"name\":\"referencePoint\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#referencePoint\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":1024,\"name\":\"fadeOutDuration\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#fadeOutDuration\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":1024,\"name\":\"highlighterOpacity\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#highlighterOpacity\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":1024,\"name\":\"laserShadowOpacity\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#laserShadowOpacity\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":262144,\"name\":\"brush\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#brush\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":262144,\"name\":\"canvas\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#canvas\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":262144,\"name\":\"context\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#context\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":262144,\"name\":\"offset\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#offset\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":262144,\"name\":\"points\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#points\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":262144,\"name\":\"scale\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#scale\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"addLayer\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#addLayer\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"addPoint\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#addPoint\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"adjustOpacity\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#adjustOpacity\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"beginStroke\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#beginStroke\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"cancelStroke\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#cancelStroke\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"clear\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#clear\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"endStroke\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#endStroke\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"fadeOut\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#fadeOut\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"getBrushCssColor\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#getBrushCssColor\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"getDefaultBrush\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#getDefaultBrush\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"internalAddPoint\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#internalAddPoint\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"internalBeginStroke\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#internalBeginStroke\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"internalCancelStroke\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#internalCancelStroke\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"internalEndStroke\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#internalEndStroke\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"internalRender\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#internalRender\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"lineTo\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#lineTo\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"moveTo\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#moveTo\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"numsToIPointerPoint\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#numsToIPointerPoint\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"removeFromDOM\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#removeFromDOM\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"removeLayer\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#removeLayer\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"renderCircle\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#renderCircle\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"renderQuad\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#renderQuad\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"renderRectangle\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#renderRectangle\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"renderStroke\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#renderStroke\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"rendersAsynchronously\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#rendersAsynchronously\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"rendersProgressively\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#rendersProgressively\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"resize\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#resize\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"scheduleRender\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#scheduleRender\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"setBrush\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#setBrush\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":2048,\"name\":\"viewportToScreen\",\"url\":\"classes/_microsoft_live_share_canvas.LaserPointerCanvas.html#viewportToScreen\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LaserPointerCanvas\"},{\"kind\":128,\"name\":\"LiveCanvas\",\"url\":\"classes/_microsoft_live_share_canvas.LiveCanvas.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share_canvas.LiveCanvas.html#constructor\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LiveCanvas\"},{\"kind\":1024,\"name\":\"onCreateLiveCursor\",\"url\":\"classes/_microsoft_live_share_canvas.LiveCanvas.html#onCreateLiveCursor\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.LiveCanvas\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/_microsoft_live_share_canvas.LiveCanvas.html#onCreateLiveCursor.__type\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.LiveCanvas.onCreateLiveCursor\"},{\"kind\":1024,\"name\":\"onGetLocalUserPictureUrl\",\"url\":\"classes/_microsoft_live_share_canvas.LiveCanvas.html#onGetLocalUserPictureUrl\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.LiveCanvas\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/_microsoft_live_share_canvas.LiveCanvas.html#onGetLocalUserPictureUrl.__type-2\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.LiveCanvas.onGetLocalUserPictureUrl\"},{\"kind\":1024,\"name\":\"TypeName\",\"url\":\"classes/_microsoft_live_share_canvas.LiveCanvas.html#TypeName\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.LiveCanvas\"},{\"kind\":1024,\"name\":\"factory\",\"url\":\"classes/_microsoft_live_share_canvas.LiveCanvas.html#factory\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.LiveCanvas\"},{\"kind\":262144,\"name\":\"allowedRoles\",\"url\":\"classes/_microsoft_live_share_canvas.LiveCanvas.html#allowedRoles\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.LiveCanvas\"},{\"kind\":262144,\"name\":\"initializeState\",\"url\":\"classes/_microsoft_live_share_canvas.LiveCanvas.html#initializeState\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LiveCanvas\"},{\"kind\":262144,\"name\":\"isCursorShared\",\"url\":\"classes/_microsoft_live_share_canvas.LiveCanvas.html#isCursorShared\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.LiveCanvas\"},{\"kind\":262144,\"name\":\"isInitialized\",\"url\":\"classes/_microsoft_live_share_canvas.LiveCanvas.html#isInitialized\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LiveCanvas\"},{\"kind\":2048,\"name\":\"getClientInfo\",\"url\":\"classes/_microsoft_live_share_canvas.LiveCanvas.html#getClientInfo\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LiveCanvas\"},{\"kind\":2048,\"name\":\"hasInitialized\",\"url\":\"classes/_microsoft_live_share_canvas.LiveCanvas.html#hasInitialized\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.LiveCanvas\"},{\"kind\":2048,\"name\":\"initialize\",\"url\":\"classes/_microsoft_live_share_canvas.LiveCanvas.html#initialize\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.LiveCanvas\"},{\"kind\":2048,\"name\":\"initializingFirstTime\",\"url\":\"classes/_microsoft_live_share_canvas.LiveCanvas.html#initializingFirstTime\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.LiveCanvas\"},{\"kind\":2048,\"name\":\"verifyLocalUserRoles\",\"url\":\"classes/_microsoft_live_share_canvas.LiveCanvas.html#verifyLocalUserRoles\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LiveCanvas\"},{\"kind\":2048,\"name\":\"waitUntilConnected\",\"url\":\"classes/_microsoft_live_share_canvas.LiveCanvas.html#waitUntilConnected\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.LiveCanvas\"},{\"kind\":128,\"name\":\"LiveCursor\",\"url\":\"classes/_microsoft_live_share_canvas.LiveCursor.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share_canvas.LiveCursor.html#constructor\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.LiveCursor\"},{\"kind\":1024,\"name\":\"clientId\",\"url\":\"classes/_microsoft_live_share_canvas.LiveCursor.html#clientId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.LiveCursor\"},{\"kind\":262144,\"name\":\"idleTime\",\"url\":\"classes/_microsoft_live_share_canvas.LiveCursor.html#idleTime\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.LiveCursor\"},{\"kind\":262144,\"name\":\"renderedElement\",\"url\":\"classes/_microsoft_live_share_canvas.LiveCursor.html#renderedElement\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.LiveCursor\"},{\"kind\":262144,\"name\":\"userInfo\",\"url\":\"classes/_microsoft_live_share_canvas.LiveCursor.html#userInfo\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.LiveCursor\"},{\"kind\":2048,\"name\":\"internalRender\",\"url\":\"classes/_microsoft_live_share_canvas.LiveCursor.html#internalRender\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.LiveCursor\"},{\"kind\":2048,\"name\":\"setPosition\",\"url\":\"classes/_microsoft_live_share_canvas.LiveCursor.html#setPosition\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.LiveCursor\"},{\"kind\":128,\"name\":\"MulticastEvent\",\"url\":\"classes/_microsoft_live_share_canvas.MulticastEvent.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share_canvas.MulticastEvent.html#constructor\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.MulticastEvent\"},{\"kind\":2048,\"name\":\"emit\",\"url\":\"classes/_microsoft_live_share_canvas.MulticastEvent.html#emit\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.MulticastEvent\"},{\"kind\":2048,\"name\":\"off\",\"url\":\"classes/_microsoft_live_share_canvas.MulticastEvent.html#off\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.MulticastEvent\"},{\"kind\":2048,\"name\":\"on\",\"url\":\"classes/_microsoft_live_share_canvas.MulticastEvent.html#on\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.MulticastEvent\"},{\"kind\":128,\"name\":\"PointerInputProvider\",\"url\":\"classes/_microsoft_live_share_canvas.PointerInputProvider.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share_canvas.PointerInputProvider.html#constructor\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.PointerInputProvider\"},{\"kind\":1024,\"name\":\"element\",\"url\":\"classes/_microsoft_live_share_canvas.PointerInputProvider.html#element\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.PointerInputProvider\"},{\"kind\":1024,\"name\":\"pointerDownEvent\",\"url\":\"classes/_microsoft_live_share_canvas.PointerInputProvider.html#pointerDownEvent\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.PointerInputProvider\"},{\"kind\":1024,\"name\":\"pointerEnterEvent\",\"url\":\"classes/_microsoft_live_share_canvas.PointerInputProvider.html#pointerEnterEvent\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.PointerInputProvider\"},{\"kind\":1024,\"name\":\"pointerLeaveEvent\",\"url\":\"classes/_microsoft_live_share_canvas.PointerInputProvider.html#pointerLeaveEvent\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.PointerInputProvider\"},{\"kind\":1024,\"name\":\"pointerMoveEvent\",\"url\":\"classes/_microsoft_live_share_canvas.PointerInputProvider.html#pointerMoveEvent\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.PointerInputProvider\"},{\"kind\":1024,\"name\":\"pointerUpEvent\",\"url\":\"classes/_microsoft_live_share_canvas.PointerInputProvider.html#pointerUpEvent\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.PointerInputProvider\"},{\"kind\":262144,\"name\":\"isActive\",\"url\":\"classes/_microsoft_live_share_canvas.PointerInputProvider.html#isActive\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.PointerInputProvider\"},{\"kind\":262144,\"name\":\"pointerDown\",\"url\":\"classes/_microsoft_live_share_canvas.PointerInputProvider.html#pointerDown\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.PointerInputProvider\"},{\"kind\":262144,\"name\":\"pointerEnter\",\"url\":\"classes/_microsoft_live_share_canvas.PointerInputProvider.html#pointerEnter\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.PointerInputProvider\"},{\"kind\":262144,\"name\":\"pointerLeave\",\"url\":\"classes/_microsoft_live_share_canvas.PointerInputProvider.html#pointerLeave\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.PointerInputProvider\"},{\"kind\":262144,\"name\":\"pointerMove\",\"url\":\"classes/_microsoft_live_share_canvas.PointerInputProvider.html#pointerMove\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.PointerInputProvider\"},{\"kind\":262144,\"name\":\"pointerUp\",\"url\":\"classes/_microsoft_live_share_canvas.PointerInputProvider.html#pointerUp\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.PointerInputProvider\"},{\"kind\":2048,\"name\":\"activate\",\"url\":\"classes/_microsoft_live_share_canvas.PointerInputProvider.html#activate\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.PointerInputProvider\"},{\"kind\":2048,\"name\":\"deactivate\",\"url\":\"classes/_microsoft_live_share_canvas.PointerInputProvider.html#deactivate\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.PointerInputProvider\"},{\"kind\":128,\"name\":\"Stroke\",\"url\":\"classes/_microsoft_live_share_canvas.Stroke.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share_canvas.Stroke.html#constructor\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.Stroke\"},{\"kind\":262144,\"name\":\"brush\",\"url\":\"classes/_microsoft_live_share_canvas.Stroke.html#brush\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.Stroke\"},{\"kind\":262144,\"name\":\"clientId\",\"url\":\"classes/_microsoft_live_share_canvas.Stroke.html#clientId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.Stroke\"},{\"kind\":262144,\"name\":\"id\",\"url\":\"classes/_microsoft_live_share_canvas.Stroke.html#id\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.Stroke\"},{\"kind\":262144,\"name\":\"length\",\"url\":\"classes/_microsoft_live_share_canvas.Stroke.html#length\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.Stroke\"},{\"kind\":262144,\"name\":\"timeStamp\",\"url\":\"classes/_microsoft_live_share_canvas.Stroke.html#timeStamp\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.Stroke\"},{\"kind\":2048,\"name\":\"[iterator]\",\"url\":\"classes/_microsoft_live_share_canvas.Stroke.html#_iterator_\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.Stroke\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/_microsoft_live_share_canvas.Stroke.html#_iterator_._iterator_-1.__type\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.Stroke.[iterator].[iterator]\"},{\"kind\":1024,\"name\":\"next\",\"url\":\"classes/_microsoft_live_share_canvas.Stroke.html#_iterator_._iterator_-1.__type.next\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.Stroke.[iterator].[iterator].__type\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/_microsoft_live_share_canvas.Stroke.html#_iterator_._iterator_-1.__type.next.__type-1\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.Stroke.[iterator].[iterator].__type.next\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/_microsoft_live_share_canvas.Stroke.html#_iterator_._iterator_-1.__type.next.__type-1.__type-2.__type-3\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.Stroke.[iterator].[iterator].__type.next.__type.__type\"},{\"kind\":1024,\"name\":\"done\",\"url\":\"classes/_microsoft_live_share_canvas.Stroke.html#_iterator_._iterator_-1.__type.next.__type-1.__type-2.__type-3.done\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.Stroke.[iterator].[iterator].__type.next.__type.__type.__type\"},{\"kind\":1024,\"name\":\"value\",\"url\":\"classes/_microsoft_live_share_canvas.Stroke.html#_iterator_._iterator_-1.__type.next.__type-1.__type-2.__type-3.value\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.Stroke.[iterator].[iterator].__type.next.__type.__type.__type\"},{\"kind\":2048,\"name\":\"addPoint\",\"url\":\"classes/_microsoft_live_share_canvas.Stroke.html#addPoint\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.Stroke\"},{\"kind\":2048,\"name\":\"addPoints\",\"url\":\"classes/_microsoft_live_share_canvas.Stroke.html#addPoints\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.Stroke\"},{\"kind\":2048,\"name\":\"clear\",\"url\":\"classes/_microsoft_live_share_canvas.Stroke.html#clear\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.Stroke\"},{\"kind\":2048,\"name\":\"deserialize\",\"url\":\"classes/_microsoft_live_share_canvas.Stroke.html#deserialize\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.Stroke\"},{\"kind\":2048,\"name\":\"getAllPoints\",\"url\":\"classes/_microsoft_live_share_canvas.Stroke.html#getAllPoints\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.Stroke\"},{\"kind\":2048,\"name\":\"getBoundingRect\",\"url\":\"classes/_microsoft_live_share_canvas.Stroke.html#getBoundingRect\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.Stroke\"},{\"kind\":2048,\"name\":\"getIntersectionPoints\",\"url\":\"classes/_microsoft_live_share_canvas.Stroke.html#getIntersectionPoints\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.Stroke\"},{\"kind\":2048,\"name\":\"getPointAt\",\"url\":\"classes/_microsoft_live_share_canvas.Stroke.html#getPointAt\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.Stroke\"},{\"kind\":2048,\"name\":\"intersectsWithRectangle\",\"url\":\"classes/_microsoft_live_share_canvas.Stroke.html#intersectsWithRectangle\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.Stroke\"},{\"kind\":2048,\"name\":\"pointErase\",\"url\":\"classes/_microsoft_live_share_canvas.Stroke.html#pointErase\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.Stroke\"},{\"kind\":2048,\"name\":\"serialize\",\"url\":\"classes/_microsoft_live_share_canvas.Stroke.html#serialize\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.Stroke\"},{\"kind\":128,\"name\":\"WetCanvas\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#constructor\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":1024,\"name\":\"referencePoint\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#referencePoint\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":1024,\"name\":\"fadeOutDuration\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#fadeOutDuration\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":1024,\"name\":\"highlighterOpacity\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#highlighterOpacity\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":1024,\"name\":\"laserShadowOpacity\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#laserShadowOpacity\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":262144,\"name\":\"brush\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#brush\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":262144,\"name\":\"canvas\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#canvas\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":262144,\"name\":\"context\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#context\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":262144,\"name\":\"offset\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#offset\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":262144,\"name\":\"points\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#points\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":262144,\"name\":\"scale\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#scale\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"addLayer\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#addLayer\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"addPoint\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#addPoint\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"adjustOpacity\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#adjustOpacity\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"beginStroke\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#beginStroke\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"cancelStroke\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#cancelStroke\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"clear\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#clear\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"endStroke\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#endStroke\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"fadeOut\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#fadeOut\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"getBrushCssColor\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#getBrushCssColor\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"getDefaultBrush\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#getDefaultBrush\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"internalAddPoint\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#internalAddPoint\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"internalBeginStroke\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#internalBeginStroke\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"internalCancelStroke\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#internalCancelStroke\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"internalEndStroke\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#internalEndStroke\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"internalRender\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#internalRender\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"lineTo\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#lineTo\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"moveTo\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#moveTo\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"numsToIPointerPoint\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#numsToIPointerPoint\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"removeFromDOM\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#removeFromDOM\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"removeLayer\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#removeLayer\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"renderCircle\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#renderCircle\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"renderQuad\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#renderQuad\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"renderRectangle\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#renderRectangle\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"renderStroke\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#renderStroke\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"rendersAsynchronously\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#rendersAsynchronously\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"rendersProgressively\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#rendersProgressively\",\"classes\":\"tsd-is-protected\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"resize\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#resize\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"scheduleRender\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#scheduleRender\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"setBrush\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#setBrush\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":2048,\"name\":\"viewportToScreen\",\"url\":\"classes/_microsoft_live_share_canvas.WetCanvas.html#viewportToScreen\",\"classes\":\"tsd-is-protected tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.WetCanvas\"},{\"kind\":256,\"name\":\"IAddPointsEventArgs\",\"url\":\"interfaces/_microsoft_live_share_canvas.IAddPointsEventArgs.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":1024,\"name\":\"endState\",\"url\":\"interfaces/_microsoft_live_share_canvas.IAddPointsEventArgs.html#endState\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IAddPointsEventArgs\"},{\"kind\":1024,\"name\":\"points\",\"url\":\"interfaces/_microsoft_live_share_canvas.IAddPointsEventArgs.html#points\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IAddPointsEventArgs\"},{\"kind\":1024,\"name\":\"strokeId\",\"url\":\"interfaces/_microsoft_live_share_canvas.IAddPointsEventArgs.html#strokeId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IAddPointsEventArgs\"},{\"kind\":256,\"name\":\"IAddRemoveStrokeOptions\",\"url\":\"interfaces/_microsoft_live_share_canvas.IAddRemoveStrokeOptions.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":1024,\"name\":\"addToChangeLog\",\"url\":\"interfaces/_microsoft_live_share_canvas.IAddRemoveStrokeOptions.html#addToChangeLog\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IAddRemoveStrokeOptions\"},{\"kind\":1024,\"name\":\"forceReRender\",\"url\":\"interfaces/_microsoft_live_share_canvas.IAddRemoveStrokeOptions.html#forceReRender\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IAddRemoveStrokeOptions\"},{\"kind\":256,\"name\":\"IBeginStrokeEventArgs\",\"url\":\"interfaces/_microsoft_live_share_canvas.IBeginStrokeEventArgs.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":1024,\"name\":\"brush\",\"url\":\"interfaces/_microsoft_live_share_canvas.IBeginStrokeEventArgs.html#brush\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IBeginStrokeEventArgs\"},{\"kind\":1024,\"name\":\"mode\",\"url\":\"interfaces/_microsoft_live_share_canvas.IBeginStrokeEventArgs.html#mode\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IBeginStrokeEventArgs\"},{\"kind\":1024,\"name\":\"startPoint\",\"url\":\"interfaces/_microsoft_live_share_canvas.IBeginStrokeEventArgs.html#startPoint\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IBeginStrokeEventArgs\"},{\"kind\":1024,\"name\":\"strokeId\",\"url\":\"interfaces/_microsoft_live_share_canvas.IBeginStrokeEventArgs.html#strokeId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IBeginStrokeEventArgs\"},{\"kind\":1024,\"name\":\"type\",\"url\":\"interfaces/_microsoft_live_share_canvas.IBeginStrokeEventArgs.html#type\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IBeginStrokeEventArgs\"},{\"kind\":256,\"name\":\"IBrush\",\"url\":\"interfaces/_microsoft_live_share_canvas.IBrush.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":1024,\"name\":\"color\",\"url\":\"interfaces/_microsoft_live_share_canvas.IBrush.html#color\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IBrush\"},{\"kind\":1024,\"name\":\"endArrow\",\"url\":\"interfaces/_microsoft_live_share_canvas.IBrush.html#endArrow\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IBrush\"},{\"kind\":1024,\"name\":\"tip\",\"url\":\"interfaces/_microsoft_live_share_canvas.IBrush.html#tip\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IBrush\"},{\"kind\":1024,\"name\":\"tipSize\",\"url\":\"interfaces/_microsoft_live_share_canvas.IBrush.html#tipSize\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IBrush\"},{\"kind\":1024,\"name\":\"type\",\"url\":\"interfaces/_microsoft_live_share_canvas.IBrush.html#type\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IBrush\"},{\"kind\":256,\"name\":\"IColor\",\"url\":\"interfaces/_microsoft_live_share_canvas.IColor.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":1024,\"name\":\"b\",\"url\":\"interfaces/_microsoft_live_share_canvas.IColor.html#b\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IColor\"},{\"kind\":1024,\"name\":\"g\",\"url\":\"interfaces/_microsoft_live_share_canvas.IColor.html#g\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IColor\"},{\"kind\":1024,\"name\":\"r\",\"url\":\"interfaces/_microsoft_live_share_canvas.IColor.html#r\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IColor\"},{\"kind\":256,\"name\":\"IMulticastEvent\",\"url\":\"interfaces/_microsoft_live_share_canvas.IMulticastEvent.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":2048,\"name\":\"off\",\"url\":\"interfaces/_microsoft_live_share_canvas.IMulticastEvent.html#off\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IMulticastEvent\"},{\"kind\":2048,\"name\":\"on\",\"url\":\"interfaces/_microsoft_live_share_canvas.IMulticastEvent.html#on\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IMulticastEvent\"},{\"kind\":256,\"name\":\"IPoint\",\"url\":\"interfaces/_microsoft_live_share_canvas.IPoint.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":1024,\"name\":\"x\",\"url\":\"interfaces/_microsoft_live_share_canvas.IPoint.html#x\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IPoint\"},{\"kind\":1024,\"name\":\"y\",\"url\":\"interfaces/_microsoft_live_share_canvas.IPoint.html#y\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IPoint\"},{\"kind\":256,\"name\":\"IPointerEvent\",\"url\":\"interfaces/_microsoft_live_share_canvas.IPointerEvent.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":1024,\"name\":\"altKey\",\"url\":\"interfaces/_microsoft_live_share_canvas.IPointerEvent.html#altKey\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IPointerEvent\"},{\"kind\":1024,\"name\":\"ctrlKey\",\"url\":\"interfaces/_microsoft_live_share_canvas.IPointerEvent.html#ctrlKey\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IPointerEvent\"},{\"kind\":1024,\"name\":\"pressure\",\"url\":\"interfaces/_microsoft_live_share_canvas.IPointerEvent.html#pressure\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.IPointerEvent\"},{\"kind\":1024,\"name\":\"shiftKey\",\"url\":\"interfaces/_microsoft_live_share_canvas.IPointerEvent.html#shiftKey\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IPointerEvent\"},{\"kind\":1024,\"name\":\"x\",\"url\":\"interfaces/_microsoft_live_share_canvas.IPointerEvent.html#x\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.IPointerEvent\"},{\"kind\":1024,\"name\":\"y\",\"url\":\"interfaces/_microsoft_live_share_canvas.IPointerEvent.html#y\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.IPointerEvent\"},{\"kind\":256,\"name\":\"IPointerMoveEvent\",\"url\":\"interfaces/_microsoft_live_share_canvas.IPointerMoveEvent.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":1024,\"name\":\"altKey\",\"url\":\"interfaces/_microsoft_live_share_canvas.IPointerMoveEvent.html#altKey\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.IPointerMoveEvent\"},{\"kind\":1024,\"name\":\"ctrlKey\",\"url\":\"interfaces/_microsoft_live_share_canvas.IPointerMoveEvent.html#ctrlKey\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.IPointerMoveEvent\"},{\"kind\":1024,\"name\":\"isPointerDown\",\"url\":\"interfaces/_microsoft_live_share_canvas.IPointerMoveEvent.html#isPointerDown\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IPointerMoveEvent\"},{\"kind\":1024,\"name\":\"pressure\",\"url\":\"interfaces/_microsoft_live_share_canvas.IPointerMoveEvent.html#pressure\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.IPointerMoveEvent\"},{\"kind\":1024,\"name\":\"shiftKey\",\"url\":\"interfaces/_microsoft_live_share_canvas.IPointerMoveEvent.html#shiftKey\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.IPointerMoveEvent\"},{\"kind\":1024,\"name\":\"x\",\"url\":\"interfaces/_microsoft_live_share_canvas.IPointerMoveEvent.html#x\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.IPointerMoveEvent\"},{\"kind\":1024,\"name\":\"y\",\"url\":\"interfaces/_microsoft_live_share_canvas.IPointerMoveEvent.html#y\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.IPointerMoveEvent\"},{\"kind\":256,\"name\":\"IPointerMovedEventArgs\",\"url\":\"interfaces/_microsoft_live_share_canvas.IPointerMovedEventArgs.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":1024,\"name\":\"position\",\"url\":\"interfaces/_microsoft_live_share_canvas.IPointerMovedEventArgs.html#position\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IPointerMovedEventArgs\"},{\"kind\":256,\"name\":\"IPointerPoint\",\"url\":\"interfaces/_microsoft_live_share_canvas.IPointerPoint.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":1024,\"name\":\"pressure\",\"url\":\"interfaces/_microsoft_live_share_canvas.IPointerPoint.html#pressure\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IPointerPoint\"},{\"kind\":1024,\"name\":\"x\",\"url\":\"interfaces/_microsoft_live_share_canvas.IPointerPoint.html#x\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.IPointerPoint\"},{\"kind\":1024,\"name\":\"y\",\"url\":\"interfaces/_microsoft_live_share_canvas.IPointerPoint.html#y\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.IPointerPoint\"},{\"kind\":256,\"name\":\"IRawStroke\",\"url\":\"interfaces/_microsoft_live_share_canvas.IRawStroke.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":1024,\"name\":\"brush\",\"url\":\"interfaces/_microsoft_live_share_canvas.IRawStroke.html#brush\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IRawStroke\"},{\"kind\":1024,\"name\":\"points\",\"url\":\"interfaces/_microsoft_live_share_canvas.IRawStroke.html#points\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IRawStroke\"},{\"kind\":256,\"name\":\"IRect\",\"url\":\"interfaces/_microsoft_live_share_canvas.IRect.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":1024,\"name\":\"bottom\",\"url\":\"interfaces/_microsoft_live_share_canvas.IRect.html#bottom\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IRect\"},{\"kind\":1024,\"name\":\"left\",\"url\":\"interfaces/_microsoft_live_share_canvas.IRect.html#left\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IRect\"},{\"kind\":1024,\"name\":\"right\",\"url\":\"interfaces/_microsoft_live_share_canvas.IRect.html#right\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IRect\"},{\"kind\":1024,\"name\":\"top\",\"url\":\"interfaces/_microsoft_live_share_canvas.IRect.html#top\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IRect\"},{\"kind\":256,\"name\":\"ISegment\",\"url\":\"interfaces/_microsoft_live_share_canvas.ISegment.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":1024,\"name\":\"from\",\"url\":\"interfaces/_microsoft_live_share_canvas.ISegment.html#from\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.ISegment\"},{\"kind\":1024,\"name\":\"to\",\"url\":\"interfaces/_microsoft_live_share_canvas.ISegment.html#to\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.ISegment\"},{\"kind\":256,\"name\":\"IStroke\",\"url\":\"interfaces/_microsoft_live_share_canvas.IStroke.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":1024,\"name\":\"brush\",\"url\":\"interfaces/_microsoft_live_share_canvas.IStroke.html#brush\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IStroke\"},{\"kind\":1024,\"name\":\"clientId\",\"url\":\"interfaces/_microsoft_live_share_canvas.IStroke.html#clientId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IStroke\"},{\"kind\":1024,\"name\":\"id\",\"url\":\"interfaces/_microsoft_live_share_canvas.IStroke.html#id\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IStroke\"},{\"kind\":1024,\"name\":\"length\",\"url\":\"interfaces/_microsoft_live_share_canvas.IStroke.html#length\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IStroke\"},{\"kind\":1024,\"name\":\"timeStamp\",\"url\":\"interfaces/_microsoft_live_share_canvas.IStroke.html#timeStamp\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IStroke\"},{\"kind\":2048,\"name\":\"addPoints\",\"url\":\"interfaces/_microsoft_live_share_canvas.IStroke.html#addPoints\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IStroke\"},{\"kind\":2048,\"name\":\"deserialize\",\"url\":\"interfaces/_microsoft_live_share_canvas.IStroke.html#deserialize\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IStroke\"},{\"kind\":2048,\"name\":\"getAllPoints\",\"url\":\"interfaces/_microsoft_live_share_canvas.IStroke.html#getAllPoints\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IStroke\"},{\"kind\":2048,\"name\":\"getBoundingRect\",\"url\":\"interfaces/_microsoft_live_share_canvas.IStroke.html#getBoundingRect\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IStroke\"},{\"kind\":2048,\"name\":\"getIntersectionPoints\",\"url\":\"interfaces/_microsoft_live_share_canvas.IStroke.html#getIntersectionPoints\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IStroke\"},{\"kind\":2048,\"name\":\"getPointAt\",\"url\":\"interfaces/_microsoft_live_share_canvas.IStroke.html#getPointAt\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IStroke\"},{\"kind\":2048,\"name\":\"intersectsWithRectangle\",\"url\":\"interfaces/_microsoft_live_share_canvas.IStroke.html#intersectsWithRectangle\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IStroke\"},{\"kind\":2048,\"name\":\"pointErase\",\"url\":\"interfaces/_microsoft_live_share_canvas.IStroke.html#pointErase\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IStroke\"},{\"kind\":2048,\"name\":\"serialize\",\"url\":\"interfaces/_microsoft_live_share_canvas.IStroke.html#serialize\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IStroke\"},{\"kind\":256,\"name\":\"IStrokeCreationOptions\",\"url\":\"interfaces/_microsoft_live_share_canvas.IStrokeCreationOptions.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":1024,\"name\":\"brush\",\"url\":\"interfaces/_microsoft_live_share_canvas.IStrokeCreationOptions.html#brush\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IStrokeCreationOptions\"},{\"kind\":1024,\"name\":\"clientId\",\"url\":\"interfaces/_microsoft_live_share_canvas.IStrokeCreationOptions.html#clientId\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IStrokeCreationOptions\"},{\"kind\":1024,\"name\":\"id\",\"url\":\"interfaces/_microsoft_live_share_canvas.IStrokeCreationOptions.html#id\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IStrokeCreationOptions\"},{\"kind\":1024,\"name\":\"points\",\"url\":\"interfaces/_microsoft_live_share_canvas.IStrokeCreationOptions.html#points\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IStrokeCreationOptions\"},{\"kind\":1024,\"name\":\"timeStamp\",\"url\":\"interfaces/_microsoft_live_share_canvas.IStrokeCreationOptions.html#timeStamp\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IStrokeCreationOptions\"},{\"kind\":256,\"name\":\"IUserInfo\",\"url\":\"interfaces/_microsoft_live_share_canvas.IUserInfo.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":1024,\"name\":\"displayName\",\"url\":\"interfaces/_microsoft_live_share_canvas.IUserInfo.html#displayName\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IUserInfo\"},{\"kind\":1024,\"name\":\"pictureUri\",\"url\":\"interfaces/_microsoft_live_share_canvas.IUserInfo.html#pictureUri\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.IUserInfo\"},{\"kind\":256,\"name\":\"IWetStroke\",\"url\":\"interfaces/_microsoft_live_share_canvas.IWetStroke.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":1024,\"name\":\"brush\",\"url\":\"interfaces/_microsoft_live_share_canvas.IWetStroke.html#brush\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.IWetStroke\"},{\"kind\":1024,\"name\":\"clientId\",\"url\":\"interfaces/_microsoft_live_share_canvas.IWetStroke.html#clientId\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.IWetStroke\"},{\"kind\":1024,\"name\":\"id\",\"url\":\"interfaces/_microsoft_live_share_canvas.IWetStroke.html#id\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.IWetStroke\"},{\"kind\":1024,\"name\":\"length\",\"url\":\"interfaces/_microsoft_live_share_canvas.IWetStroke.html#length\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.IWetStroke\"},{\"kind\":1024,\"name\":\"mode\",\"url\":\"interfaces/_microsoft_live_share_canvas.IWetStroke.html#mode\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IWetStroke\"},{\"kind\":1024,\"name\":\"timeStamp\",\"url\":\"interfaces/_microsoft_live_share_canvas.IWetStroke.html#timeStamp\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.IWetStroke\"},{\"kind\":1024,\"name\":\"type\",\"url\":\"interfaces/_microsoft_live_share_canvas.IWetStroke.html#type\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IWetStroke\"},{\"kind\":2048,\"name\":\"addPoints\",\"url\":\"interfaces/_microsoft_live_share_canvas.IWetStroke.html#addPoints\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.IWetStroke\"},{\"kind\":2048,\"name\":\"cancel\",\"url\":\"interfaces/_microsoft_live_share_canvas.IWetStroke.html#cancel\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IWetStroke\"},{\"kind\":2048,\"name\":\"deserialize\",\"url\":\"interfaces/_microsoft_live_share_canvas.IWetStroke.html#deserialize\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.IWetStroke\"},{\"kind\":2048,\"name\":\"end\",\"url\":\"interfaces/_microsoft_live_share_canvas.IWetStroke.html#end\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IWetStroke\"},{\"kind\":2048,\"name\":\"getAllPoints\",\"url\":\"interfaces/_microsoft_live_share_canvas.IWetStroke.html#getAllPoints\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.IWetStroke\"},{\"kind\":2048,\"name\":\"getBoundingRect\",\"url\":\"interfaces/_microsoft_live_share_canvas.IWetStroke.html#getBoundingRect\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.IWetStroke\"},{\"kind\":2048,\"name\":\"getIntersectionPoints\",\"url\":\"interfaces/_microsoft_live_share_canvas.IWetStroke.html#getIntersectionPoints\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.IWetStroke\"},{\"kind\":2048,\"name\":\"getPointAt\",\"url\":\"interfaces/_microsoft_live_share_canvas.IWetStroke.html#getPointAt\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.IWetStroke\"},{\"kind\":2048,\"name\":\"intersectsWithRectangle\",\"url\":\"interfaces/_microsoft_live_share_canvas.IWetStroke.html#intersectsWithRectangle\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.IWetStroke\"},{\"kind\":2048,\"name\":\"pointErase\",\"url\":\"interfaces/_microsoft_live_share_canvas.IWetStroke.html#pointErase\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.IWetStroke\"},{\"kind\":2048,\"name\":\"serialize\",\"url\":\"interfaces/_microsoft_live_share_canvas.IWetStroke.html#serialize\",\"classes\":\"tsd-is-inherited\",\"parent\":\"_microsoft_live_share_canvas.IWetStroke\"},{\"kind\":2048,\"name\":\"straighten\",\"url\":\"interfaces/_microsoft_live_share_canvas.IWetStroke.html#straighten\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.IWetStroke\"},{\"kind\":4194304,\"name\":\"ArrowType\",\"url\":\"types/_microsoft_live_share_canvas.ArrowType.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":4194304,\"name\":\"BrushTipShape\",\"url\":\"types/_microsoft_live_share_canvas.BrushTipShape.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":4194304,\"name\":\"BrushType\",\"url\":\"types/_microsoft_live_share_canvas.BrushType.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":4194304,\"name\":\"CanvasReferencePoint\",\"url\":\"types/_microsoft_live_share_canvas.CanvasReferencePoint.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":4194304,\"name\":\"EventListener\",\"url\":\"types/_microsoft_live_share_canvas.EventListener.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/_microsoft_live_share_canvas.EventListener.html#__type\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.EventListener\"},{\"kind\":32,\"name\":\"AddPointsEvent\",\"url\":\"variables/_microsoft_live_share_canvas.AddPointsEvent.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":32,\"name\":\"BasicColors\",\"url\":\"variables/_microsoft_live_share_canvas.BasicColors.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"variables/_microsoft_live_share_canvas.BasicColors.html#__type\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.BasicColors\"},{\"kind\":1024,\"name\":\"black\",\"url\":\"variables/_microsoft_live_share_canvas.BasicColors.html#__type.black\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.BasicColors.__type\"},{\"kind\":1024,\"name\":\"blue\",\"url\":\"variables/_microsoft_live_share_canvas.BasicColors.html#__type.blue\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.BasicColors.__type\"},{\"kind\":1024,\"name\":\"gray\",\"url\":\"variables/_microsoft_live_share_canvas.BasicColors.html#__type.gray\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.BasicColors.__type\"},{\"kind\":1024,\"name\":\"green\",\"url\":\"variables/_microsoft_live_share_canvas.BasicColors.html#__type.green\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.BasicColors.__type\"},{\"kind\":1024,\"name\":\"magenta\",\"url\":\"variables/_microsoft_live_share_canvas.BasicColors.html#__type.magenta\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.BasicColors.__type\"},{\"kind\":1024,\"name\":\"purple\",\"url\":\"variables/_microsoft_live_share_canvas.BasicColors.html#__type.purple\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.BasicColors.__type\"},{\"kind\":1024,\"name\":\"red\",\"url\":\"variables/_microsoft_live_share_canvas.BasicColors.html#__type.red\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.BasicColors.__type\"},{\"kind\":1024,\"name\":\"silver\",\"url\":\"variables/_microsoft_live_share_canvas.BasicColors.html#__type.silver\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.BasicColors.__type\"},{\"kind\":1024,\"name\":\"violet\",\"url\":\"variables/_microsoft_live_share_canvas.BasicColors.html#__type.violet\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.BasicColors.__type\"},{\"kind\":1024,\"name\":\"white\",\"url\":\"variables/_microsoft_live_share_canvas.BasicColors.html#__type.white\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.BasicColors.__type\"},{\"kind\":1024,\"name\":\"yellow\",\"url\":\"variables/_microsoft_live_share_canvas.BasicColors.html#__type.yellow\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.BasicColors.__type\"},{\"kind\":32,\"name\":\"BeginStrokeEvent\",\"url\":\"variables/_microsoft_live_share_canvas.BeginStrokeEvent.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":32,\"name\":\"ClearEvent\",\"url\":\"variables/_microsoft_live_share_canvas.ClearEvent.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":32,\"name\":\"DefaultHighlighterBrush\",\"url\":\"variables/_microsoft_live_share_canvas.DefaultHighlighterBrush.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":32,\"name\":\"DefaultLaserPointerBrush\",\"url\":\"variables/_microsoft_live_share_canvas.DefaultLaserPointerBrush.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":32,\"name\":\"DefaultLineBrush\",\"url\":\"variables/_microsoft_live_share_canvas.DefaultLineBrush.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":32,\"name\":\"DefaultPenBrush\",\"url\":\"variables/_microsoft_live_share_canvas.DefaultPenBrush.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":32,\"name\":\"HighlighterColors\",\"url\":\"variables/_microsoft_live_share_canvas.HighlighterColors.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"variables/_microsoft_live_share_canvas.HighlighterColors.html#__type\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.HighlighterColors\"},{\"kind\":1024,\"name\":\"Pink\",\"url\":\"variables/_microsoft_live_share_canvas.HighlighterColors.html#__type.Pink\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.HighlighterColors.__type\"},{\"kind\":1024,\"name\":\"aqua\",\"url\":\"variables/_microsoft_live_share_canvas.HighlighterColors.html#__type.aqua\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.HighlighterColors.__type\"},{\"kind\":1024,\"name\":\"black\",\"url\":\"variables/_microsoft_live_share_canvas.HighlighterColors.html#__type.black\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.HighlighterColors.__type\"},{\"kind\":1024,\"name\":\"blue\",\"url\":\"variables/_microsoft_live_share_canvas.HighlighterColors.html#__type.blue\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.HighlighterColors.__type\"},{\"kind\":1024,\"name\":\"crimson\",\"url\":\"variables/_microsoft_live_share_canvas.HighlighterColors.html#__type.crimson\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.HighlighterColors.__type\"},{\"kind\":1024,\"name\":\"gray\",\"url\":\"variables/_microsoft_live_share_canvas.HighlighterColors.html#__type.gray\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.HighlighterColors.__type\"},{\"kind\":1024,\"name\":\"green\",\"url\":\"variables/_microsoft_live_share_canvas.HighlighterColors.html#__type.green\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.HighlighterColors.__type\"},{\"kind\":1024,\"name\":\"lavender\",\"url\":\"variables/_microsoft_live_share_canvas.HighlighterColors.html#__type.lavender\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.HighlighterColors.__type\"},{\"kind\":1024,\"name\":\"lightGray\",\"url\":\"variables/_microsoft_live_share_canvas.HighlighterColors.html#__type.lightGray\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.HighlighterColors.__type\"},{\"kind\":1024,\"name\":\"lightGreen\",\"url\":\"variables/_microsoft_live_share_canvas.HighlighterColors.html#__type.lightGreen\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.HighlighterColors.__type\"},{\"kind\":1024,\"name\":\"lime\",\"url\":\"variables/_microsoft_live_share_canvas.HighlighterColors.html#__type.lime\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.HighlighterColors.__type\"},{\"kind\":1024,\"name\":\"orange\",\"url\":\"variables/_microsoft_live_share_canvas.HighlighterColors.html#__type.orange\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.HighlighterColors.__type\"},{\"kind\":1024,\"name\":\"paleBlue\",\"url\":\"variables/_microsoft_live_share_canvas.HighlighterColors.html#__type.paleBlue\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.HighlighterColors.__type\"},{\"kind\":1024,\"name\":\"red\",\"url\":\"variables/_microsoft_live_share_canvas.HighlighterColors.html#__type.red\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.HighlighterColors.__type\"},{\"kind\":1024,\"name\":\"rose\",\"url\":\"variables/_microsoft_live_share_canvas.HighlighterColors.html#__type.rose\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.HighlighterColors.__type\"},{\"kind\":1024,\"name\":\"yellow\",\"url\":\"variables/_microsoft_live_share_canvas.HighlighterColors.html#__type.yellow\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.HighlighterColors.__type\"},{\"kind\":32,\"name\":\"PenColors\",\"url\":\"variables/_microsoft_live_share_canvas.PenColors.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"variables/_microsoft_live_share_canvas.PenColors.html#__type\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.PenColors\"},{\"kind\":1024,\"name\":\"black\",\"url\":\"variables/_microsoft_live_share_canvas.PenColors.html#__type.black\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.PenColors.__type\"},{\"kind\":1024,\"name\":\"darkBlue\",\"url\":\"variables/_microsoft_live_share_canvas.PenColors.html#__type.darkBlue\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.PenColors.__type\"},{\"kind\":1024,\"name\":\"darkGray\",\"url\":\"variables/_microsoft_live_share_canvas.PenColors.html#__type.darkGray\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.PenColors.__type\"},{\"kind\":1024,\"name\":\"green\",\"url\":\"variables/_microsoft_live_share_canvas.PenColors.html#__type.green\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.PenColors.__type\"},{\"kind\":1024,\"name\":\"indigo\",\"url\":\"variables/_microsoft_live_share_canvas.PenColors.html#__type.indigo\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.PenColors.__type\"},{\"kind\":1024,\"name\":\"lightBlue\",\"url\":\"variables/_microsoft_live_share_canvas.PenColors.html#__type.lightBlue\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.PenColors.__type\"},{\"kind\":1024,\"name\":\"lightGray\",\"url\":\"variables/_microsoft_live_share_canvas.PenColors.html#__type.lightGray\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.PenColors.__type\"},{\"kind\":1024,\"name\":\"lightGreen\",\"url\":\"variables/_microsoft_live_share_canvas.PenColors.html#__type.lightGreen\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.PenColors.__type\"},{\"kind\":1024,\"name\":\"orange\",\"url\":\"variables/_microsoft_live_share_canvas.PenColors.html#__type.orange\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.PenColors.__type\"},{\"kind\":1024,\"name\":\"pink\",\"url\":\"variables/_microsoft_live_share_canvas.PenColors.html#__type.pink\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.PenColors.__type\"},{\"kind\":1024,\"name\":\"plum\",\"url\":\"variables/_microsoft_live_share_canvas.PenColors.html#__type.plum\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.PenColors.__type\"},{\"kind\":1024,\"name\":\"purple\",\"url\":\"variables/_microsoft_live_share_canvas.PenColors.html#__type.purple\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.PenColors.__type\"},{\"kind\":1024,\"name\":\"red\",\"url\":\"variables/_microsoft_live_share_canvas.PenColors.html#__type.red\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.PenColors.__type\"},{\"kind\":1024,\"name\":\"skyBlue\",\"url\":\"variables/_microsoft_live_share_canvas.PenColors.html#__type.skyBlue\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.PenColors.__type\"},{\"kind\":1024,\"name\":\"white\",\"url\":\"variables/_microsoft_live_share_canvas.PenColors.html#__type.white\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.PenColors.__type\"},{\"kind\":1024,\"name\":\"yellow\",\"url\":\"variables/_microsoft_live_share_canvas.PenColors.html#__type.yellow\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas.PenColors.__type\"},{\"kind\":32,\"name\":\"PointerMovedEvent\",\"url\":\"variables/_microsoft_live_share_canvas.PointerMovedEvent.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":32,\"name\":\"StrokesAddedEvent\",\"url\":\"variables/_microsoft_live_share_canvas.StrokesAddedEvent.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":32,\"name\":\"StrokesRemovedEvent\",\"url\":\"variables/_microsoft_live_share_canvas.StrokesRemovedEvent.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":64,\"name\":\"combineRects\",\"url\":\"functions/_microsoft_live_share_canvas.combineRects.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":64,\"name\":\"darkenColor\",\"url\":\"functions/_microsoft_live_share_canvas.darkenColor.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":64,\"name\":\"expandRect\",\"url\":\"functions/_microsoft_live_share_canvas.expandRect.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":64,\"name\":\"fromCssColor\",\"url\":\"functions/_microsoft_live_share_canvas.fromCssColor.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":64,\"name\":\"getDistanceBetweenPoints\",\"url\":\"functions/_microsoft_live_share_canvas.getDistanceBetweenPoints.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":64,\"name\":\"getPressureAdjustedSize\",\"url\":\"functions/_microsoft_live_share_canvas.getPressureAdjustedSize.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":64,\"name\":\"getSquaredDistanceBetweenPoints\",\"url\":\"functions/_microsoft_live_share_canvas.getSquaredDistanceBetweenPoints.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":64,\"name\":\"lightenColor\",\"url\":\"functions/_microsoft_live_share_canvas.lightenColor.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":64,\"name\":\"screenToViewport\",\"url\":\"functions/_microsoft_live_share_canvas.screenToViewport.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":64,\"name\":\"toCssRgbaColor\",\"url\":\"functions/_microsoft_live_share_canvas.toCssRgbaColor.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"},{\"kind\":64,\"name\":\"viewportToScreen\",\"url\":\"functions/_microsoft_live_share_canvas.viewportToScreen.html\",\"classes\":\"\",\"parent\":\"_microsoft_live_share_canvas\"}],\"index\":{\"version\":\"2.3.9\",\"fields\":[\"name\",\"comment\"],\"fieldVectors\":[[\"name/0\",[0,65.653]],[\"comment/0\",[]],[\"name/1\",[1,60.544]],[\"comment/1\",[]],[\"name/2\",[2,65.653]],[\"comment/2\",[]],[\"name/3\",[3,65.653]],[\"comment/3\",[]],[\"name/4\",[4,65.653]],[\"comment/4\",[]],[\"name/5\",[5,65.653]],[\"comment/5\",[]],[\"name/6\",[6,65.653]],[\"comment/6\",[]],[\"name/7\",[7,65.653]],[\"comment/7\",[]],[\"name/8\",[8,65.653]],[\"comment/8\",[]],[\"name/9\",[9,65.653]],[\"comment/9\",[]],[\"name/10\",[10,60.544]],[\"comment/10\",[]],[\"name/11\",[11,60.544]],[\"comment/11\",[]],[\"name/12\",[12,65.653]],[\"comment/12\",[]],[\"name/13\",[13,65.653]],[\"comment/13\",[]],[\"name/14\",[14,65.653]],[\"comment/14\",[]],[\"name/15\",[15,65.653]],[\"comment/15\",[]],[\"name/16\",[16,65.653]],[\"comment/16\",[]],[\"name/17\",[17,65.653]],[\"comment/17\",[]],[\"name/18\",[18,65.653]],[\"comment/18\",[]],[\"name/19\",[19,65.653]],[\"comment/19\",[]],[\"name/20\",[20,65.653]],[\"comment/20\",[]],[\"name/21\",[21,65.653]],[\"comment/21\",[]],[\"name/22\",[22,60.544]],[\"comment/22\",[]],[\"name/23\",[23,60.544]],[\"comment/23\",[]],[\"name/24\",[24,65.653]],[\"comment/24\",[]],[\"name/25\",[22,60.544]],[\"comment/25\",[]],[\"name/26\",[25,65.653]],[\"comment/26\",[]],[\"name/27\",[23,60.544]],[\"comment/27\",[]],[\"name/28\",[26,65.653]],[\"comment/28\",[]],[\"name/29\",[27,65.653]],[\"comment/29\",[]],[\"name/30\",[28,65.653]],[\"comment/30\",[]],[\"name/31\",[29,60.544]],[\"comment/31\",[]],[\"name/32\",[30,65.653]],[\"comment/32\",[]],[\"name/33\",[31,65.653]],[\"comment/33\",[]],[\"name/34\",[32,65.653]],[\"comment/34\",[]],[\"name/35\",[33,65.653]],[\"comment/35\",[]],[\"name/36\",[34,65.653]],[\"comment/36\",[]],[\"name/37\",[35,65.653]],[\"comment/37\",[]],[\"name/38\",[36,65.653]],[\"comment/38\",[]],[\"name/39\",[37,65.653]],[\"comment/39\",[]],[\"name/40\",[38,65.653]],[\"comment/40\",[]],[\"name/41\",[39,65.653]],[\"comment/41\",[]],[\"name/42\",[40,65.653]],[\"comment/42\",[]],[\"name/43\",[41,65.653]],[\"comment/43\",[]],[\"name/44\",[42,43.68]],[\"comment/44\",[]],[\"name/45\",[43,57.18]],[\"comment/45\",[]],[\"name/46\",[44,57.18]],[\"comment/46\",[]],[\"name/47\",[45,57.18]],[\"comment/47\",[]],[\"name/48\",[46,57.18]],[\"comment/48\",[]],[\"name/49\",[47,52.66]],[\"comment/49\",[]],[\"name/50\",[48,57.18]],[\"comment/50\",[]],[\"name/51\",[49,60.544]],[\"comment/51\",[]],[\"name/52\",[50,57.18]],[\"comment/52\",[]],[\"name/53\",[51,60.544]],[\"comment/53\",[]],[\"name/54\",[52,65.653]],[\"comment/54\",[]],[\"name/55\",[53,32.212]],[\"comment/55\",[]],[\"name/56\",[54,65.653]],[\"comment/56\",[]],[\"name/57\",[55,65.653]],[\"comment/57\",[]],[\"name/58\",[56,65.653]],[\"comment/58\",[]],[\"name/59\",[53,32.212]],[\"comment/59\",[]],[\"name/60\",[57,57.18]],[\"comment/60\",[]],[\"name/61\",[58,57.18]],[\"comment/61\",[]],[\"name/62\",[47,52.66]],[\"comment/62\",[]],[\"name/63\",[59,54.667]],[\"comment/63\",[]],[\"name/64\",[60,52.66]],[\"comment/64\",[]],[\"name/65\",[61,54.667]],[\"comment/65\",[]],[\"name/66\",[62,65.653]],[\"comment/66\",[]],[\"name/67\",[53,32.212]],[\"comment/67\",[]],[\"name/68\",[63,47.194]],[\"comment/68\",[]],[\"name/69\",[64,47.194]],[\"comment/69\",[]],[\"name/70\",[42,43.68]],[\"comment/70\",[]],[\"name/71\",[65,47.194]],[\"comment/71\",[]],[\"name/72\",[66,47.194]],[\"comment/72\",[]],[\"name/73\",[67,65.653]],[\"comment/73\",[]],[\"name/74\",[53,32.212]],[\"comment/74\",[]],[\"name/75\",[68,48.307]],[\"comment/75\",[]],[\"name/76\",[69,48.307]],[\"comment/76\",[]],[\"name/77\",[63,47.194]],[\"comment/77\",[]],[\"name/78\",[64,47.194]],[\"comment/78\",[]],[\"name/79\",[42,43.68]],[\"comment/79\",[]],[\"name/80\",[70,49.558]],[\"comment/80\",[]],[\"name/81\",[71,65.653]],[\"comment/81\",[]],[\"name/82\",[65,47.194]],[\"comment/82\",[]],[\"name/83\",[66,47.194]],[\"comment/83\",[]],[\"name/84\",[72,65.653]],[\"comment/84\",[]],[\"name/85\",[73,65.653]],[\"comment/85\",[]],[\"name/86\",[53,32.212]],[\"comment/86\",[]],[\"name/87\",[74,60.544]],[\"comment/87\",[]],[\"name/88\",[75,43.68]],[\"comment/88\",[]],[\"name/89\",[76,65.653]],[\"comment/89\",[]],[\"name/90\",[77,65.653]],[\"comment/90\",[]],[\"name/91\",[78,54.667]],[\"comment/91\",[]],[\"name/92\",[79,65.653]],[\"comment/92\",[]],[\"name/93\",[53,32.212]],[\"comment/93\",[]],[\"name/94\",[78,54.667]],[\"comment/94\",[]],[\"name/95\",[80,65.653]],[\"comment/95\",[]],[\"name/96\",[53,32.212]],[\"comment/96\",[]],[\"name/97\",[78,54.667]],[\"comment/97\",[]],[\"name/98\",[81,65.653]],[\"comment/98\",[]],[\"name/99\",[53,32.212]],[\"comment/99\",[]],[\"name/100\",[82,65.653]],[\"comment/100\",[]],[\"name/101\",[83,65.653]],[\"comment/101\",[]],[\"name/102\",[57,57.18]],[\"comment/102\",[]],[\"name/103\",[78,54.667]],[\"comment/103\",[]],[\"name/104\",[60,52.66]],[\"comment/104\",[]],[\"name/105\",[61,54.667]],[\"comment/105\",[]],[\"name/106\",[84,65.653]],[\"comment/106\",[]],[\"name/107\",[53,32.212]],[\"comment/107\",[]],[\"name/108\",[68,48.307]],[\"comment/108\",[]],[\"name/109\",[69,48.307]],[\"comment/109\",[]],[\"name/110\",[63,47.194]],[\"comment/110\",[]],[\"name/111\",[64,47.194]],[\"comment/111\",[]],[\"name/112\",[85,60.544]],[\"comment/112\",[]],[\"name/113\",[86,57.18]],[\"comment/113\",[]],[\"name/114\",[87,60.544]],[\"comment/114\",[]],[\"name/115\",[88,54.667]],[\"comment/115\",[]],[\"name/116\",[89,65.653]],[\"comment/116\",[]],[\"name/117\",[10,60.544]],[\"comment/117\",[]],[\"name/118\",[42,43.68]],[\"comment/118\",[]],[\"name/119\",[90,60.544]],[\"comment/119\",[]],[\"name/120\",[91,65.653]],[\"comment/120\",[]],[\"name/121\",[92,60.544]],[\"comment/121\",[]],[\"name/122\",[93,60.544]],[\"comment/122\",[]],[\"name/123\",[94,54.667]],[\"comment/123\",[]],[\"name/124\",[70,49.558]],[\"comment/124\",[]],[\"name/125\",[95,57.18]],[\"comment/125\",[]],[\"name/126\",[96,65.653]],[\"comment/126\",[]],[\"name/127\",[97,65.653]],[\"comment/127\",[]],[\"name/128\",[98,65.653]],[\"comment/128\",[]],[\"name/129\",[99,60.544]],[\"comment/129\",[]],[\"name/130\",[65,47.194]],[\"comment/130\",[]],[\"name/131\",[66,47.194]],[\"comment/131\",[]],[\"name/132\",[100,65.653]],[\"comment/132\",[]],[\"name/133\",[53,32.212]],[\"comment/133\",[]],[\"name/134\",[68,48.307]],[\"comment/134\",[]],[\"name/135\",[69,48.307]],[\"comment/135\",[]],[\"name/136\",[101,65.653]],[\"comment/136\",[]],[\"name/137\",[63,47.194]],[\"comment/137\",[]],[\"name/138\",[64,47.194]],[\"comment/138\",[]],[\"name/139\",[85,60.544]],[\"comment/139\",[]],[\"name/140\",[88,54.667]],[\"comment/140\",[]],[\"name/141\",[42,43.68]],[\"comment/141\",[]],[\"name/142\",[90,60.544]],[\"comment/142\",[]],[\"name/143\",[92,60.544]],[\"comment/143\",[]],[\"name/144\",[93,60.544]],[\"comment/144\",[]],[\"name/145\",[70,49.558]],[\"comment/145\",[]],[\"name/146\",[99,60.544]],[\"comment/146\",[]],[\"name/147\",[65,47.194]],[\"comment/147\",[]],[\"name/148\",[66,47.194]],[\"comment/148\",[]],[\"name/149\",[102,65.653]],[\"comment/149\",[]],[\"name/150\",[103,54.667]],[\"comment/150\",[]],[\"name/151\",[104,57.18]],[\"comment/151\",[]],[\"name/152\",[105,65.653]],[\"comment/152\",[]],[\"name/153\",[106,60.544]],[\"comment/153\",[]],[\"name/154\",[86,57.18]],[\"comment/154\",[]],[\"name/155\",[107,60.544]],[\"comment/155\",[]],[\"name/156\",[108,65.653]],[\"comment/156\",[]],[\"name/157\",[109,65.653]],[\"comment/157\",[]],[\"name/158\",[110,65.653]],[\"comment/158\",[]],[\"name/159\",[111,65.653]],[\"comment/159\",[]],[\"name/160\",[53,32.212]],[\"comment/160\",[]],[\"name/161\",[112,60.544]],[\"comment/161\",[]],[\"name/162\",[113,49.558]],[\"comment/162\",[]],[\"name/163\",[114,60.544]],[\"comment/163\",[]],[\"name/164\",[115,65.653]],[\"comment/164\",[]],[\"name/165\",[116,65.653]],[\"comment/165\",[]],[\"name/166\",[53,32.212]],[\"comment/166\",[]],[\"name/167\",[117,65.653]],[\"comment/167\",[]],[\"name/168\",[113,49.558]],[\"comment/168\",[]],[\"name/169\",[118,65.653]],[\"comment/169\",[]],[\"name/170\",[119,65.653]],[\"comment/170\",[]],[\"name/171\",[120,54.667]],[\"comment/171\",[]],[\"name/172\",[42,43.68]],[\"comment/172\",[]],[\"name/173\",[59,54.667]],[\"comment/173\",[]],[\"name/174\",[49,60.544]],[\"comment/174\",[]],[\"name/175\",[121,65.653]],[\"comment/175\",[]],[\"name/176\",[60,52.66]],[\"comment/176\",[]],[\"name/177\",[61,54.667]],[\"comment/177\",[]],[\"name/178\",[122,65.653]],[\"comment/178\",[]],[\"name/179\",[123,65.653]],[\"comment/179\",[]],[\"name/180\",[53,32.212]],[\"comment/180\",[]],[\"name/181\",[68,48.307]],[\"comment/181\",[]],[\"name/182\",[69,48.307]],[\"comment/182\",[]],[\"name/183\",[63,47.194]],[\"comment/183\",[]],[\"name/184\",[64,47.194]],[\"comment/184\",[]],[\"name/185\",[86,57.18]],[\"comment/185\",[]],[\"name/186\",[88,54.667]],[\"comment/186\",[]],[\"name/187\",[42,43.68]],[\"comment/187\",[]],[\"name/188\",[70,49.558]],[\"comment/188\",[]],[\"name/189\",[124,65.653]],[\"comment/189\",[]],[\"name/190\",[65,47.194]],[\"comment/190\",[]],[\"name/191\",[66,47.194]],[\"comment/191\",[]],[\"name/192\",[125,65.653]],[\"comment/192\",[]],[\"name/193\",[53,32.212]],[\"comment/193\",[]],[\"name/194\",[126,65.653]],[\"comment/194\",[]],[\"name/195\",[127,65.653]],[\"comment/195\",[]],[\"name/196\",[128,65.653]],[\"comment/196\",[]],[\"name/197\",[129,65.653]],[\"comment/197\",[]],[\"name/198\",[130,65.653]],[\"comment/198\",[]],[\"name/199\",[53,32.212]],[\"comment/199\",[]],[\"name/200\",[68,48.307]],[\"comment/200\",[]],[\"name/201\",[69,48.307]],[\"comment/201\",[]],[\"name/202\",[63,47.194]],[\"comment/202\",[]],[\"name/203\",[64,47.194]],[\"comment/203\",[]],[\"name/204\",[131,65.653]],[\"comment/204\",[]],[\"name/205\",[88,54.667]],[\"comment/205\",[]],[\"name/206\",[42,43.68]],[\"comment/206\",[]],[\"name/207\",[70,49.558]],[\"comment/207\",[]],[\"name/208\",[132,54.667]],[\"comment/208\",[]],[\"name/209\",[133,54.667]],[\"comment/209\",[]],[\"name/210\",[60,52.66]],[\"comment/210\",[]],[\"name/211\",[65,47.194]],[\"comment/211\",[]],[\"name/212\",[66,47.194]],[\"comment/212\",[]],[\"name/213\",[134,65.653]],[\"comment/213\",[]],[\"name/214\",[53,32.212]],[\"comment/214\",[]],[\"name/215\",[58,57.18]],[\"comment/215\",[]],[\"name/216\",[59,54.667]],[\"comment/216\",[]],[\"name/217\",[135,65.653]],[\"comment/217\",[]],[\"name/218\",[136,65.653]],[\"comment/218\",[]],[\"name/219\",[137,65.653]],[\"comment/219\",[]],[\"name/220\",[138,65.653]],[\"comment/220\",[]],[\"name/221\",[139,65.653]],[\"comment/221\",[]],[\"name/222\",[42,43.68]],[\"comment/222\",[]],[\"name/223\",[43,57.18]],[\"comment/223\",[]],[\"name/224\",[44,57.18]],[\"comment/224\",[]],[\"name/225\",[45,57.18]],[\"comment/225\",[]],[\"name/226\",[46,57.18]],[\"comment/226\",[]],[\"name/227\",[47,52.66]],[\"comment/227\",[]],[\"name/228\",[48,57.18]],[\"comment/228\",[]],[\"name/229\",[50,57.18]],[\"comment/229\",[]],[\"name/230\",[51,60.544]],[\"comment/230\",[]],[\"name/231\",[120,54.667]],[\"comment/231\",[]],[\"name/232\",[53,32.212]],[\"comment/232\",[]],[\"name/233\",[57,57.18]],[\"comment/233\",[]],[\"name/234\",[58,57.18]],[\"comment/234\",[]],[\"name/235\",[47,52.66]],[\"comment/235\",[]],[\"name/236\",[59,54.667]],[\"comment/236\",[]],[\"name/237\",[60,52.66]],[\"comment/237\",[]],[\"name/238\",[61,54.667]],[\"comment/238\",[]],[\"name/239\",[140,65.653]],[\"comment/239\",[]],[\"name/240\",[104,57.18]],[\"comment/240\",[]],[\"name/241\",[106,60.544]],[\"comment/241\",[]],[\"name/242\",[107,60.544]],[\"comment/242\",[]],[\"name/243\",[141,65.653]],[\"comment/243\",[]],[\"name/244\",[75,43.68]],[\"comment/244\",[]],[\"name/245\",[142,48.307]],[\"comment/245\",[]],[\"name/246\",[143,65.653]],[\"comment/246\",[]],[\"name/247\",[144,54.667]],[\"comment/247\",[]],[\"name/248\",[145,54.667]],[\"comment/248\",[]],[\"name/249\",[146,60.544]],[\"comment/249\",[]],[\"name/250\",[147,65.653]],[\"comment/250\",[]],[\"name/251\",[148,57.18]],[\"comment/251\",[]],[\"name/252\",[149,65.653]],[\"comment/252\",[]],[\"name/253\",[150,65.653]],[\"comment/253\",[]],[\"name/254\",[1,60.544]],[\"comment/254\",[]],[\"name/255\",[151,65.653]],[\"comment/255\",[]],[\"name/256\",[152,65.653]],[\"comment/256\",[]],[\"name/257\",[153,65.653]],[\"comment/257\",[]],[\"name/258\",[154,65.653]],[\"comment/258\",[]],[\"name/259\",[155,65.653]],[\"comment/259\",[]],[\"name/260\",[156,65.653]],[\"comment/260\",[]],[\"name/261\",[157,60.544]],[\"comment/261\",[]],[\"name/262\",[158,65.653]],[\"comment/262\",[]],[\"name/263\",[159,65.653]],[\"comment/263\",[]],[\"name/264\",[157,60.544]],[\"comment/264\",[]],[\"name/265\",[160,65.653]],[\"comment/265\",[]],[\"name/266\",[161,65.653]],[\"comment/266\",[]],[\"name/267\",[162,54.667]],[\"comment/267\",[]],[\"name/268\",[163,60.544]],[\"comment/268\",[]],[\"name/269\",[164,65.653]],[\"comment/269\",[]],[\"name/270\",[75,43.68]],[\"comment/270\",[]],[\"name/271\",[103,54.667]],[\"comment/271\",[]],[\"name/272\",[148,57.18]],[\"comment/272\",[]],[\"name/273\",[142,48.307]],[\"comment/273\",[]],[\"name/274\",[165,65.653]],[\"comment/274\",[]],[\"name/275\",[166,65.653]],[\"comment/275\",[]],[\"name/276\",[167,65.653]],[\"comment/276\",[]],[\"name/277\",[168,65.653]],[\"comment/277\",[]],[\"name/278\",[113,49.558]],[\"comment/278\",[]],[\"name/279\",[169,65.653]],[\"comment/279\",[]],[\"name/280\",[170,57.18]],[\"comment/280\",[]],[\"name/281\",[171,65.653]],[\"comment/281\",[]],[\"name/282\",[120,54.667]],[\"comment/282\",[]],[\"name/283\",[172,65.653]],[\"comment/283\",[]],[\"name/284\",[42,43.68]],[\"comment/284\",[]],[\"name/285\",[43,57.18]],[\"comment/285\",[]],[\"name/286\",[44,57.18]],[\"comment/286\",[]],[\"name/287\",[45,57.18]],[\"comment/287\",[]],[\"name/288\",[46,57.18]],[\"comment/288\",[]],[\"name/289\",[47,52.66]],[\"comment/289\",[]],[\"name/290\",[48,57.18]],[\"comment/290\",[]],[\"name/291\",[50,57.18]],[\"comment/291\",[]],[\"name/292\",[173,65.653]],[\"comment/292\",[]],[\"name/293\",[174,65.653]],[\"comment/293\",[]],[\"name/294\",[175,65.653]],[\"comment/294\",[]],[\"name/295\",[176,65.653]],[\"comment/295\",[]],[\"name/296\",[120,54.667]],[\"comment/296\",[]],[\"name/297\",[177,65.653]],[\"comment/297\",[]],[\"name/298\",[178,65.653]],[\"comment/298\",[]],[\"name/299\",[75,43.68]],[\"comment/299\",[]],[\"name/300\",[179,65.653]],[\"comment/300\",[]],[\"name/301\",[180,65.653]],[\"comment/301\",[]],[\"name/302\",[142,48.307]],[\"comment/302\",[]],[\"name/303\",[181,65.653]],[\"comment/303\",[]],[\"name/304\",[182,65.653]],[\"comment/304\",[]],[\"name/305\",[183,65.653]],[\"comment/305\",[]],[\"name/306\",[184,65.653]],[\"comment/306\",[]],[\"name/307\",[185,65.653]],[\"comment/307\",[]],[\"name/308\",[75,43.68]],[\"comment/308\",[]],[\"name/309\",[186,65.653]],[\"comment/309\",[]],[\"name/310\",[170,57.18]],[\"comment/310\",[]],[\"name/311\",[144,54.667]],[\"comment/311\",[]],[\"name/312\",[145,54.667]],[\"comment/312\",[]],[\"name/313\",[146,60.544]],[\"comment/313\",[]],[\"name/314\",[187,65.653]],[\"comment/314\",[]],[\"name/315\",[75,43.68]],[\"comment/315\",[]],[\"name/316\",[188,65.653]],[\"comment/316\",[]],[\"name/317\",[189,57.18]],[\"comment/317\",[]],[\"name/318\",[190,54.667]],[\"comment/318\",[]],[\"name/319\",[191,60.544]],[\"comment/319\",[]],[\"name/320\",[192,65.653]],[\"comment/320\",[]],[\"name/321\",[189,57.18]],[\"comment/321\",[]],[\"name/322\",[190,54.667]],[\"comment/322\",[]],[\"name/323\",[191,60.544]],[\"comment/323\",[]],[\"name/324\",[193,65.653]],[\"comment/324\",[]],[\"name/325\",[194,65.653]],[\"comment/325\",[]],[\"name/326\",[195,40.53]],[\"comment/326\",[]],[\"name/327\",[196,65.653]],[\"comment/327\",[]],[\"name/328\",[195,40.53]],[\"comment/328\",[]],[\"name/329\",[197,65.653]],[\"comment/329\",[]],[\"name/330\",[195,40.53]],[\"comment/330\",[]],[\"name/331\",[198,65.653]],[\"comment/331\",[]],[\"name/332\",[199,65.653]],[\"comment/332\",[]],[\"name/333\",[200,60.544]],[\"comment/333\",[]],[\"name/334\",[201,65.653]],[\"comment/334\",[]],[\"name/335\",[202,65.653]],[\"comment/335\",[]],[\"name/336\",[203,65.653]],[\"comment/336\",[]],[\"name/337\",[204,60.544]],[\"comment/337\",[]],[\"name/338\",[205,65.653]],[\"comment/338\",[]],[\"name/339\",[206,65.653]],[\"comment/339\",[]],[\"name/340\",[207,65.653]],[\"comment/340\",[]],[\"name/341\",[204,60.544]],[\"comment/341\",[]],[\"name/342\",[208,65.653]],[\"comment/342\",[]],[\"name/343\",[209,65.653]],[\"comment/343\",[]],[\"name/344\",[53,32.212]],[\"comment/344\",[]],[\"name/345\",[68,48.307]],[\"comment/345\",[]],[\"name/346\",[69,48.307]],[\"comment/346\",[]],[\"name/347\",[210,65.653]],[\"comment/347\",[]],[\"name/348\",[211,65.653]],[\"comment/348\",[]],[\"name/349\",[63,47.194]],[\"comment/349\",[]],[\"name/350\",[64,47.194]],[\"comment/350\",[]],[\"name/351\",[170,57.18]],[\"comment/351\",[]],[\"name/352\",[42,43.68]],[\"comment/352\",[]],[\"name/353\",[94,54.667]],[\"comment/353\",[]],[\"name/354\",[70,49.558]],[\"comment/354\",[]],[\"name/355\",[212,65.653]],[\"comment/355\",[]],[\"name/356\",[213,65.653]],[\"comment/356\",[]],[\"name/357\",[214,65.653]],[\"comment/357\",[]],[\"name/358\",[65,47.194]],[\"comment/358\",[]],[\"name/359\",[66,47.194]],[\"comment/359\",[]],[\"name/360\",[215,65.653]],[\"comment/360\",[]],[\"name/361\",[216,65.653]],[\"comment/361\",[]],[\"name/362\",[217,65.653]],[\"comment/362\",[]],[\"name/363\",[218,65.653]],[\"comment/363\",[]],[\"name/364\",[219,65.653]],[\"comment/364\",[]],[\"name/365\",[220,65.653]],[\"comment/365\",[]],[\"name/366\",[221,65.653]],[\"comment/366\",[]],[\"name/367\",[222,65.653]],[\"comment/367\",[]],[\"name/368\",[223,65.653]],[\"comment/368\",[]],[\"name/369\",[87,60.544]],[\"comment/369\",[]],[\"name/370\",[224,65.653]],[\"comment/370\",[]],[\"name/371\",[132,54.667]],[\"comment/371\",[]],[\"name/372\",[133,54.667]],[\"comment/372\",[]],[\"name/373\",[225,60.544]],[\"comment/373\",[]],[\"name/374\",[226,60.544]],[\"comment/374\",[]],[\"name/375\",[227,60.544]],[\"comment/375\",[]],[\"name/376\",[228,65.653]],[\"comment/376\",[]],[\"name/377\",[53,32.212]],[\"comment/377\",[]],[\"name/378\",[229,60.544]],[\"comment/378\",[]],[\"name/379\",[230,54.667]],[\"comment/379\",[]],[\"name/380\",[231,65.653]],[\"comment/380\",[]],[\"name/381\",[53,32.212]],[\"comment/381\",[]],[\"name/382\",[232,65.653]],[\"comment/382\",[]],[\"name/383\",[233,65.653]],[\"comment/383\",[]],[\"name/384\",[234,65.653]],[\"comment/384\",[]],[\"name/385\",[235,60.544]],[\"comment/385\",[]],[\"name/386\",[236,60.544]],[\"comment/386\",[]],[\"name/387\",[237,65.653]],[\"comment/387\",[]],[\"name/388\",[230,54.667]],[\"comment/388\",[]],[\"name/389\",[238,65.653]],[\"comment/389\",[]],[\"name/390\",[132,54.667]],[\"comment/390\",[]],[\"name/391\",[133,54.667]],[\"comment/391\",[]],[\"name/392\",[239,60.544]],[\"comment/392\",[]],[\"name/393\",[225,60.544]],[\"comment/393\",[]],[\"name/394\",[226,60.544]],[\"comment/394\",[]],[\"name/395\",[227,60.544]],[\"comment/395\",[]],[\"name/396\",[240,65.653]],[\"comment/396\",[]],[\"name/397\",[53,32.212]],[\"comment/397\",[]],[\"name/398\",[241,60.544]],[\"comment/398\",[]],[\"name/399\",[242,65.653]],[\"comment/399\",[]],[\"name/400\",[53,32.212]],[\"comment/400\",[]],[\"name/401\",[243,65.653]],[\"comment/401\",[]],[\"name/402\",[241,60.544]],[\"comment/402\",[]],[\"name/403\",[235,60.544]],[\"comment/403\",[]],[\"name/404\",[53,32.212]],[\"comment/404\",[]],[\"name/405\",[244,65.653]],[\"comment/405\",[]],[\"name/406\",[245,65.653]],[\"comment/406\",[]],[\"name/407\",[200,60.544]],[\"comment/407\",[]],[\"name/408\",[246,60.544]],[\"comment/408\",[]],[\"name/409\",[247,65.653]],[\"comment/409\",[]],[\"name/410\",[248,65.653]],[\"comment/410\",[]],[\"name/411\",[249,65.653]],[\"comment/411\",[]],[\"name/412\",[250,65.653]],[\"comment/412\",[]],[\"name/413\",[251,65.653]],[\"comment/413\",[]],[\"name/414\",[190,54.667]],[\"comment/414\",[]],[\"name/415\",[252,65.653]],[\"comment/415\",[]],[\"name/416\",[253,65.653]],[\"comment/416\",[]],[\"name/417\",[254,65.653]],[\"comment/417\",[]],[\"name/418\",[255,65.653]],[\"comment/418\",[]],[\"name/419\",[256,65.653]],[\"comment/419\",[]],[\"name/420\",[257,65.653]],[\"comment/420\",[]],[\"name/421\",[258,65.653]],[\"comment/421\",[]],[\"name/422\",[75,43.68]],[\"comment/422\",[]],[\"name/423\",[103,54.667]],[\"comment/423\",[]],[\"name/424\",[259,65.653]],[\"comment/424\",[]],[\"name/425\",[11,60.544]],[\"comment/425\",[]],[\"name/426\",[260,60.544]],[\"comment/426\",[]],[\"name/427\",[261,65.653]],[\"comment/427\",[]],[\"name/428\",[262,65.653]],[\"comment/428\",[]],[\"name/429\",[263,65.653]],[\"comment/429\",[]],[\"name/430\",[264,65.653]],[\"comment/430\",[]],[\"name/431\",[265,65.653]],[\"comment/431\",[]],[\"name/432\",[266,65.653]],[\"comment/432\",[]],[\"name/433\",[267,65.653]],[\"comment/433\",[]],[\"name/434\",[268,65.653]],[\"comment/434\",[]],[\"name/435\",[189,57.18]],[\"comment/435\",[]],[\"name/436\",[269,60.544]],[\"comment/436\",[]],[\"name/437\",[270,65.653]],[\"comment/437\",[]],[\"name/438\",[29,60.544]],[\"comment/438\",[]],[\"name/439\",[271,65.653]],[\"comment/439\",[]],[\"name/440\",[272,65.653]],[\"comment/440\",[]],[\"name/441\",[246,60.544]],[\"comment/441\",[]],[\"name/442\",[236,60.544]],[\"comment/442\",[]],[\"name/443\",[273,65.653]],[\"comment/443\",[]],[\"name/444\",[132,54.667]],[\"comment/444\",[]],[\"name/445\",[133,54.667]],[\"comment/445\",[]],[\"name/446\",[239,60.544]],[\"comment/446\",[]],[\"name/447\",[274,65.653]],[\"comment/447\",[]],[\"name/448\",[260,60.544]],[\"comment/448\",[]],[\"name/449\",[275,65.653]],[\"comment/449\",[]],[\"name/450\",[276,65.653]],[\"comment/450\",[]],[\"name/451\",[277,65.653]],[\"comment/451\",[]],[\"name/452\",[278,65.653]],[\"comment/452\",[]],[\"name/453\",[75,43.68]],[\"comment/453\",[]],[\"name/454\",[103,54.667]],[\"comment/454\",[]],[\"name/455\",[279,65.653]],[\"comment/455\",[]],[\"name/456\",[280,65.653]],[\"comment/456\",[]],[\"name/457\",[148,57.18]],[\"comment/457\",[]],[\"name/458\",[142,48.307]],[\"comment/458\",[]],[\"name/459\",[281,65.653]],[\"comment/459\",[]],[\"name/460\",[229,60.544]],[\"comment/460\",[]],[\"name/461\",[230,54.667]],[\"comment/461\",[]],[\"name/462\",[282,65.653]],[\"comment/462\",[]],[\"name/463\",[283,65.653]],[\"comment/463\",[]],[\"name/464\",[284,65.653]],[\"comment/464\",[]],[\"name/465\",[285,65.653]],[\"comment/465\",[]],[\"name/466\",[286,65.653]],[\"comment/466\",[]],[\"name/467\",[287,65.653]],[\"comment/467\",[]],[\"name/468\",[53,32.212]],[\"comment/468\",[]],[\"name/469\",[113,49.558]],[\"comment/469\",[]],[\"name/470\",[288,57.18]],[\"comment/470\",[]],[\"name/471\",[289,54.667]],[\"comment/471\",[]],[\"name/472\",[290,65.653]],[\"comment/472\",[]],[\"name/473\",[291,65.653]],[\"comment/473\",[]],[\"name/474\",[292,57.18]],[\"comment/474\",[]],[\"name/475\",[195,40.53]],[\"comment/475\",[]],[\"name/476\",[293,57.18]],[\"comment/476\",[]],[\"name/477\",[294,57.18]],[\"comment/477\",[]],[\"name/478\",[195,40.53]],[\"comment/478\",[]],[\"name/479\",[295,52.66]],[\"comment/479\",[]],[\"name/480\",[296,65.653]],[\"comment/480\",[]],[\"name/481\",[53,32.212]],[\"comment/481\",[]],[\"name/482\",[68,48.307]],[\"comment/482\",[]],[\"name/483\",[69,48.307]],[\"comment/483\",[]],[\"name/484\",[63,47.194]],[\"comment/484\",[]],[\"name/485\",[64,47.194]],[\"comment/485\",[]],[\"name/486\",[42,43.68]],[\"comment/486\",[]],[\"name/487\",[295,52.66]],[\"comment/487\",[]],[\"name/488\",[94,54.667]],[\"comment/488\",[]],[\"name/489\",[95,57.18]],[\"comment/489\",[]],[\"name/490\",[65,47.194]],[\"comment/490\",[]],[\"name/491\",[66,47.194]],[\"comment/491\",[]],[\"name/492\",[297,65.653]],[\"comment/492\",[]],[\"name/493\",[53,32.212]],[\"comment/493\",[]],[\"name/494\",[113,49.558]],[\"comment/494\",[]],[\"name/495\",[288,57.18]],[\"comment/495\",[]],[\"name/496\",[289,54.667]],[\"comment/496\",[]],[\"name/497\",[292,57.18]],[\"comment/497\",[]],[\"name/498\",[195,40.53]],[\"comment/498\",[]],[\"name/499\",[293,57.18]],[\"comment/499\",[]],[\"name/500\",[294,57.18]],[\"comment/500\",[]],[\"name/501\",[195,40.53]],[\"comment/501\",[]],[\"name/502\",[295,52.66]],[\"comment/502\",[]],[\"name/503\",[298,65.653]],[\"comment/503\",[]],[\"name/504\",[53,32.212]],[\"comment/504\",[]],[\"name/505\",[113,49.558]],[\"comment/505\",[]],[\"name/506\",[114,60.544]],[\"comment/506\",[]],[\"name/507\",[112,60.544]],[\"comment/507\",[]],[\"name/508\",[288,57.18]],[\"comment/508\",[]],[\"name/509\",[289,54.667]],[\"comment/509\",[]],[\"name/510\",[292,57.18]],[\"comment/510\",[]],[\"name/511\",[195,40.53]],[\"comment/511\",[]],[\"name/512\",[293,57.18]],[\"comment/512\",[]],[\"name/513\",[294,57.18]],[\"comment/513\",[]],[\"name/514\",[195,40.53]],[\"comment/514\",[]],[\"name/515\",[295,52.66]],[\"comment/515\",[]],[\"name/516\",[299,65.653]],[\"comment/516\",[]],[\"name/517\",[300,65.653]],[\"comment/517\",[]],[\"name/518\",[113,49.558]],[\"comment/518\",[]],[\"name/519\",[289,54.667]],[\"comment/519\",[]],[\"name/520\",[295,52.66]],[\"comment/520\",[]],[\"name/521\",[301,65.653]],[\"comment/521\",[]],[\"name/522\",[302,65.653]],[\"comment/522\",[]],[\"name/523\",[303,65.653]],[\"comment/523\",[]],[\"name/524\",[304,65.653]],[\"comment/524\",[]],[\"name/525\",[305,60.544]],[\"comment/525\",[]],[\"name/526\",[306,60.544]],[\"comment/526\",[]],[\"name/527\",[307,65.653]],[\"comment/527\",[]],[\"name/528\",[308,65.653]],[\"comment/528\",[]],[\"name/529\",[309,65.653]],[\"comment/529\",[]],[\"name/530\",[310,65.653]],[\"comment/530\",[]],[\"name/531\",[269,60.544]],[\"comment/531\",[]],[\"name/532\",[311,65.653]],[\"comment/532\",[]],[\"name/533\",[312,65.653]],[\"comment/533\",[]],[\"name/534\",[306,60.544]],[\"comment/534\",[]],[\"name/535\",[313,65.653]],[\"comment/535\",[]],[\"name/536\",[314,65.653]],[\"comment/536\",[]],[\"name/537\",[305,60.544]],[\"comment/537\",[]],[\"name/538\",[315,65.653]],[\"comment/538\",[]],[\"name/539\",[316,65.653]],[\"comment/539\",[]],[\"name/540\",[53,32.212]],[\"comment/540\",[]],[\"name/541\",[317,50.989]],[\"comment/541\",[]],[\"name/542\",[318,52.66]],[\"comment/542\",[]],[\"name/543\",[319,52.66]],[\"comment/543\",[]],[\"name/544\",[320,52.66]],[\"comment/544\",[]],[\"name/545\",[321,45.284]],[\"comment/545\",[]],[\"name/546\",[322,52.66]],[\"comment/546\",[]],[\"name/547\",[323,52.66]],[\"comment/547\",[]],[\"name/548\",[324,50.989]],[\"comment/548\",[]],[\"name/549\",[325,49.558]],[\"comment/549\",[]],[\"name/550\",[326,50.989]],[\"comment/550\",[]],[\"name/551\",[327,52.66]],[\"comment/551\",[]],[\"name/552\",[328,50.989]],[\"comment/552\",[]],[\"name/553\",[329,54.667]],[\"comment/553\",[]],[\"name/554\",[330,52.66]],[\"comment/554\",[]],[\"name/555\",[331,52.66]],[\"comment/555\",[]],[\"name/556\",[332,49.558]],[\"comment/556\",[]],[\"name/557\",[333,52.66]],[\"comment/557\",[]],[\"name/558\",[334,52.66]],[\"comment/558\",[]],[\"name/559\",[335,54.667]],[\"comment/559\",[]],[\"name/560\",[336,52.66]],[\"comment/560\",[]],[\"name/561\",[337,52.66]],[\"comment/561\",[]],[\"name/562\",[338,52.66]],[\"comment/562\",[]],[\"name/563\",[339,52.66]],[\"comment/563\",[]],[\"name/564\",[340,52.66]],[\"comment/564\",[]],[\"name/565\",[341,50.989]],[\"comment/565\",[]],[\"name/566\",[342,52.66]],[\"comment/566\",[]],[\"name/567\",[343,52.66]],[\"comment/567\",[]],[\"name/568\",[344,52.66]],[\"comment/568\",[]],[\"name/569\",[345,52.66]],[\"comment/569\",[]],[\"name/570\",[346,52.66]],[\"comment/570\",[]],[\"name/571\",[347,52.66]],[\"comment/571\",[]],[\"name/572\",[348,52.66]],[\"comment/572\",[]],[\"name/573\",[349,52.66]],[\"comment/573\",[]],[\"name/574\",[350,52.66]],[\"comment/574\",[]],[\"name/575\",[351,52.66]],[\"comment/575\",[]],[\"name/576\",[352,54.667]],[\"comment/576\",[]],[\"name/577\",[353,52.66]],[\"comment/577\",[]],[\"name/578\",[354,52.66]],[\"comment/578\",[]],[\"name/579\",[355,52.66]],[\"comment/579\",[]],[\"name/580\",[356,49.558]],[\"comment/580\",[]],[\"name/581\",[357,65.653]],[\"comment/581\",[]],[\"name/582\",[53,32.212]],[\"comment/582\",[]],[\"name/583\",[317,50.989]],[\"comment/583\",[]],[\"name/584\",[318,52.66]],[\"comment/584\",[]],[\"name/585\",[319,52.66]],[\"comment/585\",[]],[\"name/586\",[320,52.66]],[\"comment/586\",[]],[\"name/587\",[321,45.284]],[\"comment/587\",[]],[\"name/588\",[322,52.66]],[\"comment/588\",[]],[\"name/589\",[323,52.66]],[\"comment/589\",[]],[\"name/590\",[324,50.989]],[\"comment/590\",[]],[\"name/591\",[325,49.558]],[\"comment/591\",[]],[\"name/592\",[326,50.989]],[\"comment/592\",[]],[\"name/593\",[327,52.66]],[\"comment/593\",[]],[\"name/594\",[328,50.989]],[\"comment/594\",[]],[\"name/595\",[329,54.667]],[\"comment/595\",[]],[\"name/596\",[330,52.66]],[\"comment/596\",[]],[\"name/597\",[331,52.66]],[\"comment/597\",[]],[\"name/598\",[332,49.558]],[\"comment/598\",[]],[\"name/599\",[333,52.66]],[\"comment/599\",[]],[\"name/600\",[334,52.66]],[\"comment/600\",[]],[\"name/601\",[335,54.667]],[\"comment/601\",[]],[\"name/602\",[336,52.66]],[\"comment/602\",[]],[\"name/603\",[337,52.66]],[\"comment/603\",[]],[\"name/604\",[338,52.66]],[\"comment/604\",[]],[\"name/605\",[339,52.66]],[\"comment/605\",[]],[\"name/606\",[340,52.66]],[\"comment/606\",[]],[\"name/607\",[341,50.989]],[\"comment/607\",[]],[\"name/608\",[342,52.66]],[\"comment/608\",[]],[\"name/609\",[343,52.66]],[\"comment/609\",[]],[\"name/610\",[344,52.66]],[\"comment/610\",[]],[\"name/611\",[345,52.66]],[\"comment/611\",[]],[\"name/612\",[346,52.66]],[\"comment/612\",[]],[\"name/613\",[347,52.66]],[\"comment/613\",[]],[\"name/614\",[348,52.66]],[\"comment/614\",[]],[\"name/615\",[349,52.66]],[\"comment/615\",[]],[\"name/616\",[350,52.66]],[\"comment/616\",[]],[\"name/617\",[351,52.66]],[\"comment/617\",[]],[\"name/618\",[352,54.667]],[\"comment/618\",[]],[\"name/619\",[353,52.66]],[\"comment/619\",[]],[\"name/620\",[354,52.66]],[\"comment/620\",[]],[\"name/621\",[355,52.66]],[\"comment/621\",[]],[\"name/622\",[356,49.558]],[\"comment/622\",[]],[\"name/623\",[358,65.653]],[\"comment/623\",[]],[\"name/624\",[53,32.212]],[\"comment/624\",[]],[\"name/625\",[317,50.989]],[\"comment/625\",[]],[\"name/626\",[318,52.66]],[\"comment/626\",[]],[\"name/627\",[319,52.66]],[\"comment/627\",[]],[\"name/628\",[320,52.66]],[\"comment/628\",[]],[\"name/629\",[321,45.284]],[\"comment/629\",[]],[\"name/630\",[322,52.66]],[\"comment/630\",[]],[\"name/631\",[323,52.66]],[\"comment/631\",[]],[\"name/632\",[324,50.989]],[\"comment/632\",[]],[\"name/633\",[326,50.989]],[\"comment/633\",[]],[\"name/634\",[327,52.66]],[\"comment/634\",[]],[\"name/635\",[328,50.989]],[\"comment/635\",[]],[\"name/636\",[330,52.66]],[\"comment/636\",[]],[\"name/637\",[331,52.66]],[\"comment/637\",[]],[\"name/638\",[332,49.558]],[\"comment/638\",[]],[\"name/639\",[333,52.66]],[\"comment/639\",[]],[\"name/640\",[334,52.66]],[\"comment/640\",[]],[\"name/641\",[336,52.66]],[\"comment/641\",[]],[\"name/642\",[337,52.66]],[\"comment/642\",[]],[\"name/643\",[338,52.66]],[\"comment/643\",[]],[\"name/644\",[339,52.66]],[\"comment/644\",[]],[\"name/645\",[340,52.66]],[\"comment/645\",[]],[\"name/646\",[341,50.989]],[\"comment/646\",[]],[\"name/647\",[342,52.66]],[\"comment/647\",[]],[\"name/648\",[343,52.66]],[\"comment/648\",[]],[\"name/649\",[344,52.66]],[\"comment/649\",[]],[\"name/650\",[345,52.66]],[\"comment/650\",[]],[\"name/651\",[346,52.66]],[\"comment/651\",[]],[\"name/652\",[347,52.66]],[\"comment/652\",[]],[\"name/653\",[348,52.66]],[\"comment/653\",[]],[\"name/654\",[349,52.66]],[\"comment/654\",[]],[\"name/655\",[350,52.66]],[\"comment/655\",[]],[\"name/656\",[351,52.66]],[\"comment/656\",[]],[\"name/657\",[353,52.66]],[\"comment/657\",[]],[\"name/658\",[354,52.66]],[\"comment/658\",[]],[\"name/659\",[355,52.66]],[\"comment/659\",[]],[\"name/660\",[356,49.558]],[\"comment/660\",[]],[\"name/661\",[359,65.653]],[\"comment/661\",[]],[\"name/662\",[53,32.212]],[\"comment/662\",[]],[\"name/663\",[360,65.653]],[\"comment/663\",[]],[\"name/664\",[361,65.653]],[\"comment/664\",[]],[\"name/665\",[362,65.653]],[\"comment/665\",[]],[\"name/666\",[363,65.653]],[\"comment/666\",[]],[\"name/667\",[364,65.653]],[\"comment/667\",[]],[\"name/668\",[365,65.653]],[\"comment/668\",[]],[\"name/669\",[366,65.653]],[\"comment/669\",[]],[\"name/670\",[367,65.653]],[\"comment/670\",[]],[\"name/671\",[368,65.653]],[\"comment/671\",[]],[\"name/672\",[369,65.653]],[\"comment/672\",[]],[\"name/673\",[370,60.544]],[\"comment/673\",[]],[\"name/674\",[371,65.653]],[\"comment/674\",[]],[\"name/675\",[372,65.653]],[\"comment/675\",[]],[\"name/676\",[324,50.989]],[\"comment/676\",[]],[\"name/677\",[373,65.653]],[\"comment/677\",[]],[\"name/678\",[317,50.989]],[\"comment/678\",[]],[\"name/679\",[326,50.989]],[\"comment/679\",[]],[\"name/680\",[374,65.653]],[\"comment/680\",[]],[\"name/681\",[375,65.653]],[\"comment/681\",[]],[\"name/682\",[376,57.18]],[\"comment/682\",[]],[\"name/683\",[377,65.653]],[\"comment/683\",[]],[\"name/684\",[378,65.653]],[\"comment/684\",[]],[\"name/685\",[379,65.653]],[\"comment/685\",[]],[\"name/686\",[332,49.558]],[\"comment/686\",[]],[\"name/687\",[380,57.18]],[\"comment/687\",[]],[\"name/688\",[381,65.653]],[\"comment/688\",[]],[\"name/689\",[382,65.653]],[\"comment/689\",[]],[\"name/690\",[383,65.653]],[\"comment/690\",[]],[\"name/691\",[384,65.653]],[\"comment/691\",[]],[\"name/692\",[385,65.653]],[\"comment/692\",[]],[\"name/693\",[386,65.653]],[\"comment/693\",[]],[\"name/694\",[387,54.667]],[\"comment/694\",[]],[\"name/695\",[388,65.653]],[\"comment/695\",[]],[\"name/696\",[389,60.544]],[\"comment/696\",[]],[\"name/697\",[390,65.653]],[\"comment/697\",[]],[\"name/698\",[356,49.558]],[\"comment/698\",[]],[\"name/699\",[391,65.653]],[\"comment/699\",[]],[\"name/700\",[53,32.212]],[\"comment/700\",[]],[\"name/701\",[392,57.18]],[\"comment/701\",[]],[\"name/702\",[393,57.18]],[\"comment/702\",[]],[\"name/703\",[394,65.653]],[\"comment/703\",[]],[\"name/704\",[53,32.212]],[\"comment/704\",[]],[\"name/705\",[395,65.653]],[\"comment/705\",[]],[\"name/706\",[392,57.18]],[\"comment/706\",[]],[\"name/707\",[393,57.18]],[\"comment/707\",[]],[\"name/708\",[370,60.544]],[\"comment/708\",[]],[\"name/709\",[53,32.212]],[\"comment/709\",[]],[\"name/710\",[396,60.544]],[\"comment/710\",[]],[\"name/711\",[397,60.544]],[\"comment/711\",[]],[\"name/712\",[398,60.544]],[\"comment/712\",[]],[\"name/713\",[399,60.544]],[\"comment/713\",[]],[\"name/714\",[400,60.544]],[\"comment/714\",[]],[\"name/715\",[401,60.544]],[\"comment/715\",[]],[\"name/716\",[402,60.544]],[\"comment/716\",[]],[\"name/717\",[403,60.544]],[\"comment/717\",[]],[\"name/718\",[404,60.544]],[\"comment/718\",[]],[\"name/719\",[405,60.544]],[\"comment/719\",[]],[\"name/720\",[406,60.544]],[\"comment/720\",[]],[\"name/721\",[376,57.18]],[\"comment/721\",[]],[\"name/722\",[380,57.18]],[\"comment/722\",[]],[\"name/723\",[407,65.653]],[\"comment/723\",[]],[\"name/724\",[53,32.212]],[\"comment/724\",[]],[\"name/725\",[392,57.18]],[\"comment/725\",[]],[\"name/726\",[393,57.18]],[\"comment/726\",[]],[\"name/727\",[408,65.653]],[\"comment/727\",[]],[\"name/728\",[53,32.212]],[\"comment/728\",[]],[\"name/729\",[317,50.989]],[\"comment/729\",[]],[\"name/730\",[318,52.66]],[\"comment/730\",[]],[\"name/731\",[319,52.66]],[\"comment/731\",[]],[\"name/732\",[320,52.66]],[\"comment/732\",[]],[\"name/733\",[321,45.284]],[\"comment/733\",[]],[\"name/734\",[322,52.66]],[\"comment/734\",[]],[\"name/735\",[323,52.66]],[\"comment/735\",[]],[\"name/736\",[324,50.989]],[\"comment/736\",[]],[\"name/737\",[325,49.558]],[\"comment/737\",[]],[\"name/738\",[326,50.989]],[\"comment/738\",[]],[\"name/739\",[327,52.66]],[\"comment/739\",[]],[\"name/740\",[328,50.989]],[\"comment/740\",[]],[\"name/741\",[329,54.667]],[\"comment/741\",[]],[\"name/742\",[330,52.66]],[\"comment/742\",[]],[\"name/743\",[331,52.66]],[\"comment/743\",[]],[\"name/744\",[332,49.558]],[\"comment/744\",[]],[\"name/745\",[333,52.66]],[\"comment/745\",[]],[\"name/746\",[334,52.66]],[\"comment/746\",[]],[\"name/747\",[335,54.667]],[\"comment/747\",[]],[\"name/748\",[336,52.66]],[\"comment/748\",[]],[\"name/749\",[337,52.66]],[\"comment/749\",[]],[\"name/750\",[338,52.66]],[\"comment/750\",[]],[\"name/751\",[339,52.66]],[\"comment/751\",[]],[\"name/752\",[340,52.66]],[\"comment/752\",[]],[\"name/753\",[341,50.989]],[\"comment/753\",[]],[\"name/754\",[342,52.66]],[\"comment/754\",[]],[\"name/755\",[343,52.66]],[\"comment/755\",[]],[\"name/756\",[344,52.66]],[\"comment/756\",[]],[\"name/757\",[345,52.66]],[\"comment/757\",[]],[\"name/758\",[346,52.66]],[\"comment/758\",[]],[\"name/759\",[347,52.66]],[\"comment/759\",[]],[\"name/760\",[348,52.66]],[\"comment/760\",[]],[\"name/761\",[349,52.66]],[\"comment/761\",[]],[\"name/762\",[350,52.66]],[\"comment/762\",[]],[\"name/763\",[351,52.66]],[\"comment/763\",[]],[\"name/764\",[352,54.667]],[\"comment/764\",[]],[\"name/765\",[353,52.66]],[\"comment/765\",[]],[\"name/766\",[354,52.66]],[\"comment/766\",[]],[\"name/767\",[355,52.66]],[\"comment/767\",[]],[\"name/768\",[356,49.558]],[\"comment/768\",[]],[\"name/769\",[409,65.653]],[\"comment/769\",[]],[\"name/770\",[53,32.212]],[\"comment/770\",[]],[\"name/771\",[410,65.653]],[\"comment/771\",[]],[\"name/772\",[195,40.53]],[\"comment/772\",[]],[\"name/773\",[411,65.653]],[\"comment/773\",[]],[\"name/774\",[195,40.53]],[\"comment/774\",[]],[\"name/775\",[68,48.307]],[\"comment/775\",[]],[\"name/776\",[69,48.307]],[\"comment/776\",[]],[\"name/777\",[74,60.544]],[\"comment/777\",[]],[\"name/778\",[63,47.194]],[\"comment/778\",[]],[\"name/779\",[412,65.653]],[\"comment/779\",[]],[\"name/780\",[64,47.194]],[\"comment/780\",[]],[\"name/781\",[42,43.68]],[\"comment/781\",[]],[\"name/782\",[94,54.667]],[\"comment/782\",[]],[\"name/783\",[70,49.558]],[\"comment/783\",[]],[\"name/784\",[95,57.18]],[\"comment/784\",[]],[\"name/785\",[65,47.194]],[\"comment/785\",[]],[\"name/786\",[66,47.194]],[\"comment/786\",[]],[\"name/787\",[413,65.653]],[\"comment/787\",[]],[\"name/788\",[53,32.212]],[\"comment/788\",[]],[\"name/789\",[75,43.68]],[\"comment/789\",[]],[\"name/790\",[414,65.653]],[\"comment/790\",[]],[\"name/791\",[415,65.653]],[\"comment/791\",[]],[\"name/792\",[416,65.653]],[\"comment/792\",[]],[\"name/793\",[341,50.989]],[\"comment/793\",[]],[\"name/794\",[417,65.653]],[\"comment/794\",[]],[\"name/795\",[418,65.653]],[\"comment/795\",[]],[\"name/796\",[53,32.212]],[\"comment/796\",[]],[\"name/797\",[419,65.653]],[\"comment/797\",[]],[\"name/798\",[144,54.667]],[\"comment/798\",[]],[\"name/799\",[145,54.667]],[\"comment/799\",[]],[\"name/800\",[420,65.653]],[\"comment/800\",[]],[\"name/801\",[53,32.212]],[\"comment/801\",[]],[\"name/802\",[421,65.653]],[\"comment/802\",[]],[\"name/803\",[396,60.544]],[\"comment/803\",[]],[\"name/804\",[397,60.544]],[\"comment/804\",[]],[\"name/805\",[398,60.544]],[\"comment/805\",[]],[\"name/806\",[399,60.544]],[\"comment/806\",[]],[\"name/807\",[400,60.544]],[\"comment/807\",[]],[\"name/808\",[401,60.544]],[\"comment/808\",[]],[\"name/809\",[402,60.544]],[\"comment/809\",[]],[\"name/810\",[403,60.544]],[\"comment/810\",[]],[\"name/811\",[404,60.544]],[\"comment/811\",[]],[\"name/812\",[405,60.544]],[\"comment/812\",[]],[\"name/813\",[406,60.544]],[\"comment/813\",[]],[\"name/814\",[376,57.18]],[\"comment/814\",[]],[\"name/815\",[380,57.18]],[\"comment/815\",[]],[\"name/816\",[422,65.653]],[\"comment/816\",[]],[\"name/817\",[53,32.212]],[\"comment/817\",[]],[\"name/818\",[321,45.284]],[\"comment/818\",[]],[\"name/819\",[75,43.68]],[\"comment/819\",[]],[\"name/820\",[423,54.667]],[\"comment/820\",[]],[\"name/821\",[424,57.18]],[\"comment/821\",[]],[\"name/822\",[142,48.307]],[\"comment/822\",[]],[\"name/823\",[425,65.653]],[\"comment/823\",[]],[\"name/824\",[195,40.53]],[\"comment/824\",[]],[\"name/825\",[426,65.653]],[\"comment/825\",[]],[\"name/826\",[195,40.53]],[\"comment/826\",[]],[\"name/827\",[195,40.53]],[\"comment/827\",[]],[\"name/828\",[427,65.653]],[\"comment/828\",[]],[\"name/829\",[163,60.544]],[\"comment/829\",[]],[\"name/830\",[328,50.989]],[\"comment/830\",[]],[\"name/831\",[428,57.18]],[\"comment/831\",[]],[\"name/832\",[332,49.558]],[\"comment/832\",[]],[\"name/833\",[429,57.18]],[\"comment/833\",[]],[\"name/834\",[430,57.18]],[\"comment/834\",[]],[\"name/835\",[431,57.18]],[\"comment/835\",[]],[\"name/836\",[432,57.18]],[\"comment/836\",[]],[\"name/837\",[433,57.18]],[\"comment/837\",[]],[\"name/838\",[434,57.18]],[\"comment/838\",[]],[\"name/839\",[387,54.667]],[\"comment/839\",[]],[\"name/840\",[435,57.18]],[\"comment/840\",[]],[\"name/841\",[436,65.653]],[\"comment/841\",[]],[\"name/842\",[53,32.212]],[\"comment/842\",[]],[\"name/843\",[317,50.989]],[\"comment/843\",[]],[\"name/844\",[318,52.66]],[\"comment/844\",[]],[\"name/845\",[319,52.66]],[\"comment/845\",[]],[\"name/846\",[320,52.66]],[\"comment/846\",[]],[\"name/847\",[321,45.284]],[\"comment/847\",[]],[\"name/848\",[322,52.66]],[\"comment/848\",[]],[\"name/849\",[323,52.66]],[\"comment/849\",[]],[\"name/850\",[324,50.989]],[\"comment/850\",[]],[\"name/851\",[325,49.558]],[\"comment/851\",[]],[\"name/852\",[326,50.989]],[\"comment/852\",[]],[\"name/853\",[327,52.66]],[\"comment/853\",[]],[\"name/854\",[328,50.989]],[\"comment/854\",[]],[\"name/855\",[329,54.667]],[\"comment/855\",[]],[\"name/856\",[330,52.66]],[\"comment/856\",[]],[\"name/857\",[331,52.66]],[\"comment/857\",[]],[\"name/858\",[332,49.558]],[\"comment/858\",[]],[\"name/859\",[333,52.66]],[\"comment/859\",[]],[\"name/860\",[334,52.66]],[\"comment/860\",[]],[\"name/861\",[335,54.667]],[\"comment/861\",[]],[\"name/862\",[336,52.66]],[\"comment/862\",[]],[\"name/863\",[337,52.66]],[\"comment/863\",[]],[\"name/864\",[338,52.66]],[\"comment/864\",[]],[\"name/865\",[339,52.66]],[\"comment/865\",[]],[\"name/866\",[340,52.66]],[\"comment/866\",[]],[\"name/867\",[341,50.989]],[\"comment/867\",[]],[\"name/868\",[342,52.66]],[\"comment/868\",[]],[\"name/869\",[343,52.66]],[\"comment/869\",[]],[\"name/870\",[344,52.66]],[\"comment/870\",[]],[\"name/871\",[345,52.66]],[\"comment/871\",[]],[\"name/872\",[346,52.66]],[\"comment/872\",[]],[\"name/873\",[347,52.66]],[\"comment/873\",[]],[\"name/874\",[348,52.66]],[\"comment/874\",[]],[\"name/875\",[349,52.66]],[\"comment/875\",[]],[\"name/876\",[350,52.66]],[\"comment/876\",[]],[\"name/877\",[351,52.66]],[\"comment/877\",[]],[\"name/878\",[352,54.667]],[\"comment/878\",[]],[\"name/879\",[353,52.66]],[\"comment/879\",[]],[\"name/880\",[354,52.66]],[\"comment/880\",[]],[\"name/881\",[355,52.66]],[\"comment/881\",[]],[\"name/882\",[356,49.558]],[\"comment/882\",[]],[\"name/883\",[437,65.653]],[\"comment/883\",[]],[\"name/884\",[438,65.653]],[\"comment/884\",[]],[\"name/885\",[325,49.558]],[\"comment/885\",[]],[\"name/886\",[439,60.544]],[\"comment/886\",[]],[\"name/887\",[440,65.653]],[\"comment/887\",[]],[\"name/888\",[441,65.653]],[\"comment/888\",[]],[\"name/889\",[442,65.653]],[\"comment/889\",[]],[\"name/890\",[443,65.653]],[\"comment/890\",[]],[\"name/891\",[321,45.284]],[\"comment/891\",[]],[\"name/892\",[444,60.544]],[\"comment/892\",[]],[\"name/893\",[445,65.653]],[\"comment/893\",[]],[\"name/894\",[439,60.544]],[\"comment/894\",[]],[\"name/895\",[162,54.667]],[\"comment/895\",[]],[\"name/896\",[446,65.653]],[\"comment/896\",[]],[\"name/897\",[447,65.653]],[\"comment/897\",[]],[\"name/898\",[448,65.653]],[\"comment/898\",[]],[\"name/899\",[449,65.653]],[\"comment/899\",[]],[\"name/900\",[450,65.653]],[\"comment/900\",[]],[\"name/901\",[162,54.667]],[\"comment/901\",[]],[\"name/902\",[451,65.653]],[\"comment/902\",[]],[\"name/903\",[452,65.653]],[\"comment/903\",[]],[\"name/904\",[453,65.653]],[\"comment/904\",[]],[\"name/905\",[454,65.653]],[\"comment/905\",[]],[\"name/906\",[455,65.653]],[\"comment/906\",[]],[\"name/907\",[144,54.667]],[\"comment/907\",[]],[\"name/908\",[145,54.667]],[\"comment/908\",[]],[\"name/909\",[456,65.653]],[\"comment/909\",[]],[\"name/910\",[457,54.667]],[\"comment/910\",[]],[\"name/911\",[458,54.667]],[\"comment/911\",[]],[\"name/912\",[459,65.653]],[\"comment/912\",[]],[\"name/913\",[460,60.544]],[\"comment/913\",[]],[\"name/914\",[461,60.544]],[\"comment/914\",[]],[\"name/915\",[462,57.18]],[\"comment/915\",[]],[\"name/916\",[463,60.544]],[\"comment/916\",[]],[\"name/917\",[457,54.667]],[\"comment/917\",[]],[\"name/918\",[458,54.667]],[\"comment/918\",[]],[\"name/919\",[464,65.653]],[\"comment/919\",[]],[\"name/920\",[460,60.544]],[\"comment/920\",[]],[\"name/921\",[461,60.544]],[\"comment/921\",[]],[\"name/922\",[465,65.653]],[\"comment/922\",[]],[\"name/923\",[462,57.18]],[\"comment/923\",[]],[\"name/924\",[463,60.544]],[\"comment/924\",[]],[\"name/925\",[457,54.667]],[\"comment/925\",[]],[\"name/926\",[458,54.667]],[\"comment/926\",[]],[\"name/927\",[466,65.653]],[\"comment/927\",[]],[\"name/928\",[190,54.667]],[\"comment/928\",[]],[\"name/929\",[467,65.653]],[\"comment/929\",[]],[\"name/930\",[462,57.18]],[\"comment/930\",[]],[\"name/931\",[457,54.667]],[\"comment/931\",[]],[\"name/932\",[458,54.667]],[\"comment/932\",[]],[\"name/933\",[468,65.653]],[\"comment/933\",[]],[\"name/934\",[321,45.284]],[\"comment/934\",[]],[\"name/935\",[325,49.558]],[\"comment/935\",[]],[\"name/936\",[469,65.653]],[\"comment/936\",[]],[\"name/937\",[470,65.653]],[\"comment/937\",[]],[\"name/938\",[471,65.653]],[\"comment/938\",[]],[\"name/939\",[472,65.653]],[\"comment/939\",[]],[\"name/940\",[473,65.653]],[\"comment/940\",[]],[\"name/941\",[474,65.653]],[\"comment/941\",[]],[\"name/942\",[475,65.653]],[\"comment/942\",[]],[\"name/943\",[476,65.653]],[\"comment/943\",[]],[\"name/944\",[477,65.653]],[\"comment/944\",[]],[\"name/945\",[321,45.284]],[\"comment/945\",[]],[\"name/946\",[75,43.68]],[\"comment/946\",[]],[\"name/947\",[423,54.667]],[\"comment/947\",[]],[\"name/948\",[424,57.18]],[\"comment/948\",[]],[\"name/949\",[142,48.307]],[\"comment/949\",[]],[\"name/950\",[428,57.18]],[\"comment/950\",[]],[\"name/951\",[429,57.18]],[\"comment/951\",[]],[\"name/952\",[430,57.18]],[\"comment/952\",[]],[\"name/953\",[431,57.18]],[\"comment/953\",[]],[\"name/954\",[432,57.18]],[\"comment/954\",[]],[\"name/955\",[433,57.18]],[\"comment/955\",[]],[\"name/956\",[434,57.18]],[\"comment/956\",[]],[\"name/957\",[387,54.667]],[\"comment/957\",[]],[\"name/958\",[435,57.18]],[\"comment/958\",[]],[\"name/959\",[478,65.653]],[\"comment/959\",[]],[\"name/960\",[321,45.284]],[\"comment/960\",[]],[\"name/961\",[75,43.68]],[\"comment/961\",[]],[\"name/962\",[423,54.667]],[\"comment/962\",[]],[\"name/963\",[325,49.558]],[\"comment/963\",[]],[\"name/964\",[142,48.307]],[\"comment/964\",[]],[\"name/965\",[479,65.653]],[\"comment/965\",[]],[\"name/966\",[104,57.18]],[\"comment/966\",[]],[\"name/967\",[480,65.653]],[\"comment/967\",[]],[\"name/968\",[481,65.653]],[\"comment/968\",[]],[\"name/969\",[321,45.284]],[\"comment/969\",[]],[\"name/970\",[75,43.68]],[\"comment/970\",[]],[\"name/971\",[423,54.667]],[\"comment/971\",[]],[\"name/972\",[424,57.18]],[\"comment/972\",[]],[\"name/973\",[444,60.544]],[\"comment/973\",[]],[\"name/974\",[142,48.307]],[\"comment/974\",[]],[\"name/975\",[162,54.667]],[\"comment/975\",[]],[\"name/976\",[428,57.18]],[\"comment/976\",[]],[\"name/977\",[482,65.653]],[\"comment/977\",[]],[\"name/978\",[429,57.18]],[\"comment/978\",[]],[\"name/979\",[230,54.667]],[\"comment/979\",[]],[\"name/980\",[430,57.18]],[\"comment/980\",[]],[\"name/981\",[431,57.18]],[\"comment/981\",[]],[\"name/982\",[432,57.18]],[\"comment/982\",[]],[\"name/983\",[433,57.18]],[\"comment/983\",[]],[\"name/984\",[434,57.18]],[\"comment/984\",[]],[\"name/985\",[387,54.667]],[\"comment/985\",[]],[\"name/986\",[435,57.18]],[\"comment/986\",[]],[\"name/987\",[483,65.653]],[\"comment/987\",[]],[\"name/988\",[484,65.653]],[\"comment/988\",[]],[\"name/989\",[485,65.653]],[\"comment/989\",[]],[\"name/990\",[486,65.653]],[\"comment/990\",[]],[\"name/991\",[487,65.653]],[\"comment/991\",[]],[\"name/992\",[488,65.653]],[\"comment/992\",[]],[\"name/993\",[195,40.53]],[\"comment/993\",[]],[\"name/994\",[489,65.653]],[\"comment/994\",[]],[\"name/995\",[490,65.653]],[\"comment/995\",[]],[\"name/996\",[195,40.53]],[\"comment/996\",[]],[\"name/997\",[491,57.18]],[\"comment/997\",[]],[\"name/998\",[492,60.544]],[\"comment/998\",[]],[\"name/999\",[493,60.544]],[\"comment/999\",[]],[\"name/1000\",[494,57.18]],[\"comment/1000\",[]],[\"name/1001\",[495,65.653]],[\"comment/1001\",[]],[\"name/1002\",[496,60.544]],[\"comment/1002\",[]],[\"name/1003\",[497,57.18]],[\"comment/1003\",[]],[\"name/1004\",[498,65.653]],[\"comment/1004\",[]],[\"name/1005\",[499,65.653]],[\"comment/1005\",[]],[\"name/1006\",[500,60.544]],[\"comment/1006\",[]],[\"name/1007\",[501,57.18]],[\"comment/1007\",[]],[\"name/1008\",[502,65.653]],[\"comment/1008\",[]],[\"name/1009\",[503,65.653]],[\"comment/1009\",[]],[\"name/1010\",[504,65.653]],[\"comment/1010\",[]],[\"name/1011\",[505,65.653]],[\"comment/1011\",[]],[\"name/1012\",[506,65.653]],[\"comment/1012\",[]],[\"name/1013\",[507,65.653]],[\"comment/1013\",[]],[\"name/1014\",[508,65.653]],[\"comment/1014\",[]],[\"name/1015\",[195,40.53]],[\"comment/1015\",[]],[\"name/1016\",[509,60.544]],[\"comment/1016\",[]],[\"name/1017\",[510,65.653]],[\"comment/1017\",[]],[\"name/1018\",[491,57.18]],[\"comment/1018\",[]],[\"name/1019\",[492,60.544]],[\"comment/1019\",[]],[\"name/1020\",[511,65.653]],[\"comment/1020\",[]],[\"name/1021\",[493,60.544]],[\"comment/1021\",[]],[\"name/1022\",[494,57.18]],[\"comment/1022\",[]],[\"name/1023\",[512,65.653]],[\"comment/1023\",[]],[\"name/1024\",[513,60.544]],[\"comment/1024\",[]],[\"name/1025\",[514,60.544]],[\"comment/1025\",[]],[\"name/1026\",[515,65.653]],[\"comment/1026\",[]],[\"name/1027\",[516,60.544]],[\"comment/1027\",[]],[\"name/1028\",[517,65.653]],[\"comment/1028\",[]],[\"name/1029\",[497,57.18]],[\"comment/1029\",[]],[\"name/1030\",[518,65.653]],[\"comment/1030\",[]],[\"name/1031\",[501,57.18]],[\"comment/1031\",[]],[\"name/1032\",[519,65.653]],[\"comment/1032\",[]],[\"name/1033\",[195,40.53]],[\"comment/1033\",[]],[\"name/1034\",[491,57.18]],[\"comment/1034\",[]],[\"name/1035\",[520,65.653]],[\"comment/1035\",[]],[\"name/1036\",[521,65.653]],[\"comment/1036\",[]],[\"name/1037\",[494,57.18]],[\"comment/1037\",[]],[\"name/1038\",[522,65.653]],[\"comment/1038\",[]],[\"name/1039\",[523,65.653]],[\"comment/1039\",[]],[\"name/1040\",[513,60.544]],[\"comment/1040\",[]],[\"name/1041\",[514,60.544]],[\"comment/1041\",[]],[\"name/1042\",[516,60.544]],[\"comment/1042\",[]],[\"name/1043\",[509,60.544]],[\"comment/1043\",[]],[\"name/1044\",[524,65.653]],[\"comment/1044\",[]],[\"name/1045\",[496,60.544]],[\"comment/1045\",[]],[\"name/1046\",[497,57.18]],[\"comment/1046\",[]],[\"name/1047\",[525,65.653]],[\"comment/1047\",[]],[\"name/1048\",[500,60.544]],[\"comment/1048\",[]],[\"name/1049\",[501,57.18]],[\"comment/1049\",[]],[\"name/1050\",[526,65.653]],[\"comment/1050\",[]],[\"name/1051\",[527,65.653]],[\"comment/1051\",[]],[\"name/1052\",[528,65.653]],[\"comment/1052\",[]],[\"name/1053\",[529,65.653]],[\"comment/1053\",[]],[\"name/1054\",[530,65.653]],[\"comment/1054\",[]],[\"name/1055\",[531,65.653]],[\"comment/1055\",[]],[\"name/1056\",[532,65.653]],[\"comment/1056\",[]],[\"name/1057\",[533,65.653]],[\"comment/1057\",[]],[\"name/1058\",[534,65.653]],[\"comment/1058\",[]],[\"name/1059\",[535,65.653]],[\"comment/1059\",[]],[\"name/1060\",[536,65.653]],[\"comment/1060\",[]],[\"name/1061\",[389,60.544]],[\"comment/1061\",[]],[\"name/1062\",[537,65.653]],[\"comment/1062\",[]],[\"name/1063\",[356,49.558]],[\"comment/1063\",[]]],\"invertedIndex\":[[\"__type\",{\"_index\":195,\"name\":{\"326\":{},\"328\":{},\"330\":{},\"475\":{},\"478\":{},\"498\":{},\"501\":{},\"511\":{},\"514\":{},\"772\":{},\"774\":{},\"824\":{},\"826\":{},\"827\":{},\"993\":{},\"996\":{},\"1015\":{},\"1033\":{}},\"comment\":{}}],[\"_containerruntime\",{\"_index\":117,\"name\":{\"167\":{}},\"comment\":{}}],[\"_microsoft_live_share\",{\"_index\":0,\"name\":{\"0\":{}},\"comment\":{}}],[\"_microsoft_live_share_canvas\",{\"_index\":301,\"name\":{\"521\":{}},\"comment\":{}}],[\"_microsoft_live_share_media\",{\"_index\":199,\"name\":{\"332\":{}},\"comment\":{}}],[\"_microsoft_live_share_turbo\",{\"_index\":286,\"name\":{\"466\":{}},\"comment\":{}}],[\"action\",{\"_index\":257,\"name\":{\"420\":{}},\"comment\":{}}],[\"actionthrottler\",{\"_index\":210,\"name\":{\"347\":{}},\"comment\":{}}],[\"activate\",{\"_index\":376,\"name\":{\"682\":{},\"721\":{},\"814\":{}},\"comment\":{}}],[\"activefollowers\",{\"_index\":7,\"name\":{\"7\":{}},\"comment\":{}}],[\"activepresenter\",{\"_index\":8,\"name\":{\"8\":{}},\"comment\":{}}],[\"addclient\",{\"_index\":139,\"name\":{\"221\":{}},\"comment\":{}}],[\"added\",{\"_index\":2,\"name\":{\"2\":{}},\"comment\":{}}],[\"addeventlistener\",{\"_index\":236,\"name\":{\"386\":{},\"442\":{}},\"comment\":{}}],[\"addfilters\",{\"_index\":395,\"name\":{\"705\":{}},\"comment\":{}}],[\"addlayer\",{\"_index\":327,\"name\":{\"551\":{},\"593\":{},\"634\":{},\"739\":{},\"853\":{}},\"comment\":{}}],[\"addpoint\",{\"_index\":328,\"name\":{\"552\":{},\"594\":{},\"635\":{},\"740\":{},\"830\":{},\"854\":{}},\"comment\":{}}],[\"addpoints\",{\"_index\":428,\"name\":{\"831\":{},\"950\":{},\"976\":{}},\"comment\":{}}],[\"addpointsevent\",{\"_index\":489,\"name\":{\"994\":{}},\"comment\":{}}],[\"addstroke\",{\"_index\":377,\"name\":{\"683\":{}},\"comment\":{}}],[\"addtochangelog\",{\"_index\":441,\"name\":{\"888\":{}},\"comment\":{}}],[\"adjustopacity\",{\"_index\":329,\"name\":{\"553\":{},\"595\":{},\"741\":{},\"855\":{}},\"comment\":{}}],[\"allowedroles\",{\"_index\":74,\"name\":{\"87\":{},\"777\":{}},\"comment\":{}}],[\"alreadyexists\",{\"_index\":3,\"name\":{\"3\":{}},\"comment\":{}}],[\"altkey\",{\"_index\":460,\"name\":{\"913\":{},\"920\":{}},\"comment\":{}}],[\"aqua\",{\"_index\":510,\"name\":{\"1017\":{}},\"comment\":{}}],[\"arrowtype\",{\"_index\":484,\"name\":{\"988\":{}},\"comment\":{}}],[\"attendee\",{\"_index\":37,\"name\":{\"39\":{}},\"comment\":{}}],[\"away\",{\"_index\":33,\"name\":{\"35\":{}},\"comment\":{}}],[\"azurelivesharehost\",{\"_index\":41,\"name\":{\"43\":{}},\"comment\":{}}],[\"azureturboclient\",{\"_index\":287,\"name\":{\"467\":{}},\"comment\":{}}],[\"b\",{\"_index\":452,\"name\":{\"903\":{}},\"comment\":{}}],[\"basiccolors\",{\"_index\":490,\"name\":{\"995\":{}},\"comment\":{}}],[\"beginseek\",{\"_index\":237,\"name\":{\"387\":{}},\"comment\":{}}],[\"beginstroke\",{\"_index\":330,\"name\":{\"554\":{},\"596\":{},\"636\":{},\"742\":{},\"856\":{}},\"comment\":{}}],[\"beginstrokeevent\",{\"_index\":502,\"name\":{\"1008\":{}},\"comment\":{}}],[\"beginsuspension\",{\"_index\":87,\"name\":{\"114\":{},\"369\":{}},\"comment\":{}}],[\"beginupdate\",{\"_index\":378,\"name\":{\"684\":{}},\"comment\":{}}],[\"beginwetstroke\",{\"_index\":379,\"name\":{\"685\":{}},\"comment\":{}}],[\"black\",{\"_index\":491,\"name\":{\"997\":{},\"1018\":{},\"1034\":{}},\"comment\":{}}],[\"blocked\",{\"_index\":258,\"name\":{\"421\":{}},\"comment\":{}}],[\"blue\",{\"_index\":492,\"name\":{\"998\":{},\"1019\":{}},\"comment\":{}}],[\"bottom\",{\"_index\":470,\"name\":{\"937\":{}},\"comment\":{}}],[\"brush\",{\"_index\":321,\"name\":{\"545\":{},\"587\":{},\"629\":{},\"733\":{},\"818\":{},\"847\":{},\"891\":{},\"934\":{},\"945\":{},\"960\":{},\"969\":{}},\"comment\":{}}],[\"brushtipshape\",{\"_index\":485,\"name\":{\"989\":{}},\"comment\":{}}],[\"brushtype\",{\"_index\":486,\"name\":{\"990\":{}},\"comment\":{}}],[\"cancel\",{\"_index\":482,\"name\":{\"977\":{}},\"comment\":{}}],[\"cancelled\",{\"_index\":310,\"name\":{\"530\":{}},\"comment\":{}}],[\"cancelstroke\",{\"_index\":331,\"name\":{\"555\":{},\"597\":{},\"637\":{},\"743\":{},\"857\":{}},\"comment\":{}}],[\"canplaypause\",{\"_index\":216,\"name\":{\"361\":{}},\"comment\":{}}],[\"canseek\",{\"_index\":217,\"name\":{\"362\":{}},\"comment\":{}}],[\"cansendbackgroundupdates\",{\"_index\":113,\"name\":{\"162\":{},\"168\":{},\"278\":{},\"469\":{},\"494\":{},\"505\":{},\"518\":{}},\"comment\":{}}],[\"cansendpositionupdates\",{\"_index\":218,\"name\":{\"363\":{}},\"comment\":{}}],[\"cansettrack\",{\"_index\":219,\"name\":{\"364\":{}},\"comment\":{}}],[\"cansettrackdata\",{\"_index\":220,\"name\":{\"365\":{}},\"comment\":{}}],[\"canvas\",{\"_index\":322,\"name\":{\"546\":{},\"588\":{},\"630\":{},\"734\":{},\"848\":{}},\"comment\":{}}],[\"canvasreferencepoint\",{\"_index\":487,\"name\":{\"991\":{}},\"comment\":{}}],[\"centerx\",{\"_index\":364,\"name\":{\"667\":{}},\"comment\":{}}],[\"centery\",{\"_index\":365,\"name\":{\"668\":{}},\"comment\":{}}],[\"clear\",{\"_index\":332,\"name\":{\"556\":{},\"598\":{},\"638\":{},\"686\":{},\"744\":{},\"832\":{},\"858\":{}},\"comment\":{}}],[\"clearevent\",{\"_index\":503,\"name\":{\"1009\":{}},\"comment\":{}}],[\"clientheight\",{\"_index\":366,\"name\":{\"669\":{}},\"comment\":{}}],[\"clientid\",{\"_index\":75,\"name\":{\"88\":{},\"244\":{},\"270\":{},\"299\":{},\"308\":{},\"315\":{},\"422\":{},\"453\":{},\"789\":{},\"819\":{},\"946\":{},\"961\":{},\"970\":{}},\"comment\":{}}],[\"clientwidth\",{\"_index\":367,\"name\":{\"670\":{}},\"comment\":{}}],[\"color\",{\"_index\":447,\"name\":{\"897\":{}},\"comment\":{}}],[\"combinerects\",{\"_index\":529,\"name\":{\"1053\":{}},\"comment\":{}}],[\"configchangedat\",{\"_index\":188,\"name\":{\"316\":{}},\"comment\":{}}],[\"conflict\",{\"_index\":4,\"name\":{\"4\":{}},\"comment\":{}}],[\"connected\",{\"_index\":186,\"name\":{\"309\":{}},\"comment\":{}}],[\"connection\",{\"_index\":169,\"name\":{\"279\":{}},\"comment\":{}}],[\"constructor\",{\"_index\":53,\"name\":{\"55\":{},\"59\":{},\"67\":{},\"74\":{},\"86\":{},\"93\":{},\"96\":{},\"99\":{},\"107\":{},\"133\":{},\"160\":{},\"166\":{},\"180\":{},\"193\":{},\"199\":{},\"214\":{},\"232\":{},\"344\":{},\"377\":{},\"381\":{},\"397\":{},\"400\":{},\"404\":{},\"468\":{},\"481\":{},\"493\":{},\"504\":{},\"540\":{},\"582\":{},\"624\":{},\"662\":{},\"700\":{},\"704\":{},\"709\":{},\"724\":{},\"728\":{},\"770\":{},\"788\":{},\"796\":{},\"801\":{},\"817\":{},\"842\":{}},\"comment\":{}}],[\"container\",{\"_index\":174,\"name\":{\"293\":{}},\"comment\":{}}],[\"containerid\",{\"_index\":150,\"name\":{\"253\":{}},\"comment\":{}}],[\"containerstate\",{\"_index\":1,\"name\":{\"1\":{},\"254\":{}},\"comment\":{}}],[\"context\",{\"_index\":323,\"name\":{\"547\":{},\"589\":{},\"631\":{},\"735\":{},\"849\":{}},\"comment\":{}}],[\"coordinationwaitpoint\",{\"_index\":250,\"name\":{\"412\":{}},\"comment\":{}}],[\"coordinator\",{\"_index\":211,\"name\":{\"348\":{}},\"comment\":{}}],[\"coordinatorstatechange\",{\"_index\":204,\"name\":{\"337\":{},\"341\":{}},\"comment\":{}}],[\"correlationid\",{\"_index\":179,\"name\":{\"300\":{}},\"comment\":{}}],[\"create\",{\"_index\":51,\"name\":{\"53\":{},\"230\":{}},\"comment\":{}}],[\"createchildren\",{\"_index\":224,\"name\":{\"370\":{}},\"comment\":{}}],[\"createcontainer\",{\"_index\":290,\"name\":{\"472\":{}},\"comment\":{}}],[\"created\",{\"_index\":175,\"name\":{\"294\":{}},\"comment\":{}}],[\"crimson\",{\"_index\":511,\"name\":{\"1020\":{}},\"comment\":{}}],[\"ctrlkey\",{\"_index\":461,\"name\":{\"914\":{},\"921\":{}},\"comment\":{}}],[\"currentsrc\",{\"_index\":267,\"name\":{\"433\":{}},\"comment\":{}}],[\"currenttime\",{\"_index\":268,\"name\":{\"434\":{}},\"comment\":{}}],[\"darkblue\",{\"_index\":520,\"name\":{\"1035\":{}},\"comment\":{}}],[\"darkencolor\",{\"_index\":530,\"name\":{\"1054\":{}},\"comment\":{}}],[\"darkgray\",{\"_index\":521,\"name\":{\"1036\":{}},\"comment\":{}}],[\"data\",{\"_index\":103,\"name\":{\"150\":{},\"271\":{},\"423\":{},\"454\":{}},\"comment\":{}}],[\"deactivate\",{\"_index\":380,\"name\":{\"687\":{},\"722\":{},\"815\":{}},\"comment\":{}}],[\"defaulthighlighterbrush\",{\"_index\":504,\"name\":{\"1010\":{}},\"comment\":{}}],[\"defaultlaserpointerbrush\",{\"_index\":505,\"name\":{\"1011\":{}},\"comment\":{}}],[\"defaultlinebrush\",{\"_index\":506,\"name\":{\"1012\":{}},\"comment\":{}}],[\"defaultlocalroles\",{\"_index\":136,\"name\":{\"218\":{}},\"comment\":{}}],[\"defaultpenbrush\",{\"_index\":507,\"name\":{\"1013\":{}},\"comment\":{}}],[\"defaultremoteroles\",{\"_index\":137,\"name\":{\"219\":{}},\"comment\":{}}],[\"delay\",{\"_index\":83,\"name\":{\"101\":{}},\"comment\":{}}],[\"deserialize\",{\"_index\":429,\"name\":{\"833\":{},\"951\":{},\"978\":{}},\"comment\":{}}],[\"details\",{\"_index\":279,\"name\":{\"455\":{}},\"comment\":{}}],[\"displayname\",{\"_index\":104,\"name\":{\"151\":{},\"240\":{},\"966\":{}},\"comment\":{}}],[\"dispose\",{\"_index\":88,\"name\":{\"115\":{},\"140\":{},\"186\":{},\"205\":{}},\"comment\":{}}],[\"done\",{\"_index\":427,\"name\":{\"828\":{}},\"comment\":{}}],[\"drycanvas\",{\"_index\":316,\"name\":{\"539\":{}},\"comment\":{}}],[\"drywetcanvas\",{\"_index\":357,\"name\":{\"581\":{}},\"comment\":{}}],[\"duration\",{\"_index\":189,\"name\":{\"317\":{},\"321\":{},\"435\":{}},\"comment\":{}}],[\"dynamicloadableobjects\",{\"_index\":54,\"name\":{\"56\":{}},\"comment\":{}}],[\"dynamicobjectmanager\",{\"_index\":296,\"name\":{\"480\":{}},\"comment\":{}}],[\"dynamicobjectregistry\",{\"_index\":52,\"name\":{\"54\":{}},\"comment\":{}}],[\"dynamicobjecttypes\",{\"_index\":293,\"name\":{\"476\":{},\"499\":{},\"512\":{}},\"comment\":{}}],[\"element\",{\"_index\":421,\"name\":{\"802\":{}},\"comment\":{}}],[\"emit\",{\"_index\":419,\"name\":{\"797\":{}},\"comment\":{}}],[\"enablestrokemodifierhotkeys\",{\"_index\":361,\"name\":{\"664\":{}},\"comment\":{}}],[\"end\",{\"_index\":230,\"name\":{\"379\":{},\"388\":{},\"461\":{},\"979\":{}},\"comment\":{}}],[\"endarrow\",{\"_index\":448,\"name\":{\"898\":{}},\"comment\":{}}],[\"ended\",{\"_index\":269,\"name\":{\"436\":{},\"531\":{}},\"comment\":{}}],[\"endseek\",{\"_index\":238,\"name\":{\"389\":{}},\"comment\":{}}],[\"endstate\",{\"_index\":438,\"name\":{\"884\":{}},\"comment\":{}}],[\"endstroke\",{\"_index\":333,\"name\":{\"557\":{},\"599\":{},\"639\":{},\"745\":{},\"859\":{}},\"comment\":{}}],[\"endsuspension\",{\"_index\":89,\"name\":{\"116\":{}},\"comment\":{}}],[\"endupdate\",{\"_index\":381,\"name\":{\"688\":{}},\"comment\":{}}],[\"ephemeral\",{\"_index\":314,\"name\":{\"536\":{}},\"comment\":{}}],[\"ephemeralcanvasremovaldelay\",{\"_index\":362,\"name\":{\"665\":{}},\"comment\":{}}],[\"erase\",{\"_index\":382,\"name\":{\"689\":{}},\"comment\":{}}],[\"eraser\",{\"_index\":303,\"name\":{\"523\":{}},\"comment\":{}}],[\"erasersize\",{\"_index\":360,\"name\":{\"663\":{}},\"comment\":{}}],[\"error\",{\"_index\":280,\"name\":{\"456\":{}},\"comment\":{}}],[\"eventlistener\",{\"_index\":488,\"name\":{\"992\":{}},\"comment\":{}}],[\"eventname\",{\"_index\":180,\"name\":{\"301\":{}},\"comment\":{}}],[\"expandrect\",{\"_index\":531,\"name\":{\"1055\":{}},\"comment\":{}}],[\"expirationperiod\",{\"_index\":101,\"name\":{\"136\":{}},\"comment\":{}}],[\"exportraw\",{\"_index\":383,\"name\":{\"690\":{}},\"comment\":{}}],[\"exportsvg\",{\"_index\":384,\"name\":{\"691\":{}},\"comment\":{}}],[\"extendedmediametadata\",{\"_index\":253,\"name\":{\"416\":{}},\"comment\":{}}],[\"extendedmediasessionaction\",{\"_index\":282,\"name\":{\"462\":{}},\"comment\":{}}],[\"extendedmediasessionactiondetails\",{\"_index\":256,\"name\":{\"419\":{}},\"comment\":{}}],[\"extendedmediasessionactionhandler\",{\"_index\":265,\"name\":{\"431\":{}},\"comment\":{}}],[\"extendedmediasessionactionsource\",{\"_index\":283,\"name\":{\"463\":{}},\"comment\":{}}],[\"extendedmediasessionplaybackstate\",{\"_index\":284,\"name\":{\"464\":{}},\"comment\":{}}],[\"factory\",{\"_index\":69,\"name\":{\"76\":{},\"109\":{},\"135\":{},\"182\":{},\"201\":{},\"346\":{},\"483\":{},\"776\":{}},\"comment\":{}}],[\"fadeout\",{\"_index\":334,\"name\":{\"558\":{},\"600\":{},\"640\":{},\"746\":{},\"860\":{}},\"comment\":{}}],[\"fadeoutduration\",{\"_index\":318,\"name\":{\"542\":{},\"584\":{},\"626\":{},\"730\":{},\"844\":{}},\"comment\":{}}],[\"fastseek\",{\"_index\":259,\"name\":{\"424\":{}},\"comment\":{}}],[\"fatalerror\",{\"_index\":15,\"name\":{\"15\":{}},\"comment\":{}}],[\"filterpoint\",{\"_index\":392,\"name\":{\"701\":{},\"706\":{},\"725\":{}},\"comment\":{}}],[\"finished\",{\"_index\":27,\"name\":{\"29\":{}},\"comment\":{}}],[\"fixed\",{\"_index\":201,\"name\":{\"334\":{}},\"comment\":{}}],[\"fluidturboclient\",{\"_index\":297,\"name\":{\"492\":{}},\"comment\":{}}],[\"followinguserid\",{\"_index\":157,\"name\":{\"261\":{},\"264\":{}},\"comment\":{}}],[\"followmodepresenceuser\",{\"_index\":193,\"name\":{\"324\":{}},\"comment\":{}}],[\"followmodetype\",{\"_index\":6,\"name\":{\"6\":{}},\"comment\":{}}],[\"followpresenter\",{\"_index\":9,\"name\":{\"9\":{}},\"comment\":{}}],[\"followuser\",{\"_index\":10,\"name\":{\"10\":{},\"117\":{}},\"comment\":{}}],[\"forcererender\",{\"_index\":442,\"name\":{\"889\":{}},\"comment\":{}}],[\"formatcorrelationid\",{\"_index\":129,\"name\":{\"197\":{}},\"comment\":{}}],[\"freehand\",{\"_index\":312,\"name\":{\"533\":{}},\"comment\":{}}],[\"from\",{\"_index\":475,\"name\":{\"942\":{}},\"comment\":{}}],[\"fromcsscolor\",{\"_index\":532,\"name\":{\"1056\":{}},\"comment\":{}}],[\"g\",{\"_index\":453,\"name\":{\"904\":{}},\"comment\":{}}],[\"getallpoints\",{\"_index\":430,\"name\":{\"834\":{},\"952\":{},\"980\":{}},\"comment\":{}}],[\"getboundingrect\",{\"_index\":431,\"name\":{\"835\":{},\"953\":{},\"981\":{}},\"comment\":{}}],[\"getbrushcsscolor\",{\"_index\":335,\"name\":{\"559\":{},\"601\":{},\"747\":{},\"861\":{}},\"comment\":{}}],[\"getclientinfo\",{\"_index\":42,\"name\":{\"44\":{},\"70\":{},\"79\":{},\"118\":{},\"141\":{},\"172\":{},\"187\":{},\"206\":{},\"222\":{},\"284\":{},\"352\":{},\"486\":{},\"781\":{}},\"comment\":{}}],[\"getclientroles\",{\"_index\":43,\"name\":{\"45\":{},\"223\":{},\"285\":{}},\"comment\":{}}],[\"getconnection\",{\"_index\":108,\"name\":{\"156\":{}},\"comment\":{}}],[\"getconnections\",{\"_index\":109,\"name\":{\"157\":{}},\"comment\":{}}],[\"getcontainer\",{\"_index\":291,\"name\":{\"473\":{}},\"comment\":{}}],[\"getcontainerschema\",{\"_index\":292,\"name\":{\"474\":{},\"497\":{},\"510\":{}},\"comment\":{}}],[\"getdds\",{\"_index\":295,\"name\":{\"479\":{},\"487\":{},\"502\":{},\"515\":{},\"520\":{}},\"comment\":{}}],[\"getdefaultbrush\",{\"_index\":336,\"name\":{\"560\":{},\"602\":{},\"641\":{},\"748\":{},\"862\":{}},\"comment\":{}}],[\"getdistancebetweenpoints\",{\"_index\":533,\"name\":{\"1057\":{}},\"comment\":{}}],[\"getfluidcontainerid\",{\"_index\":44,\"name\":{\"46\":{},\"224\":{},\"286\":{}},\"comment\":{}}],[\"getfluidtenantinfo\",{\"_index\":45,\"name\":{\"47\":{},\"225\":{},\"287\":{}},\"comment\":{}}],[\"getfluidtoken\",{\"_index\":46,\"name\":{\"48\":{},\"226\":{},\"288\":{}},\"comment\":{}}],[\"getintersectionpoints\",{\"_index\":432,\"name\":{\"836\":{},\"954\":{},\"982\":{}},\"comment\":{}}],[\"getlivesharecontainerschemaproxy\",{\"_index\":198,\"name\":{\"331\":{}},\"comment\":{}}],[\"getlocalusercansend\",{\"_index\":194,\"name\":{\"325\":{}},\"comment\":{}}],[\"getmaxtimestamperror\",{\"_index\":58,\"name\":{\"61\":{},\"215\":{},\"234\":{}},\"comment\":{}}],[\"getntptime\",{\"_index\":47,\"name\":{\"49\":{},\"62\":{},\"227\":{},\"235\":{},\"289\":{}},\"comment\":{}}],[\"getpointat\",{\"_index\":433,\"name\":{\"837\":{},\"955\":{},\"983\":{}},\"comment\":{}}],[\"getpressureadjustedsize\",{\"_index\":534,\"name\":{\"1058\":{}},\"comment\":{}}],[\"getsquareddistancebetweenpoints\",{\"_index\":535,\"name\":{\"1059\":{}},\"comment\":{}}],[\"getstroke\",{\"_index\":385,\"name\":{\"692\":{}},\"comment\":{}}],[\"gettimestamp\",{\"_index\":59,\"name\":{\"63\":{},\"173\":{},\"216\":{},\"236\":{}},\"comment\":{}}],[\"getuser\",{\"_index\":90,\"name\":{\"119\":{},\"142\":{}},\"comment\":{}}],[\"getuserfollowers\",{\"_index\":91,\"name\":{\"120\":{}},\"comment\":{}}],[\"getuserforclient\",{\"_index\":92,\"name\":{\"121\":{},\"143\":{}},\"comment\":{}}],[\"getusers\",{\"_index\":93,\"name\":{\"122\":{},\"144\":{}},\"comment\":{}}],[\"gray\",{\"_index\":493,\"name\":{\"999\":{},\"1021\":{}},\"comment\":{}}],[\"green\",{\"_index\":494,\"name\":{\"1000\":{},\"1022\":{},\"1037\":{}},\"comment\":{}}],[\"groupaction\",{\"_index\":205,\"name\":{\"338\":{}},\"comment\":{}}],[\"guest\",{\"_index\":38,\"name\":{\"40\":{}},\"comment\":{}}],[\"hasinitialized\",{\"_index\":94,\"name\":{\"123\":{},\"353\":{},\"488\":{},\"782\":{}},\"comment\":{}}],[\"highlighter\",{\"_index\":304,\"name\":{\"524\":{}},\"comment\":{}}],[\"highlighterbrush\",{\"_index\":368,\"name\":{\"671\":{}},\"comment\":{}}],[\"highlightercolors\",{\"_index\":508,\"name\":{\"1014\":{}},\"comment\":{}}],[\"highlighteropacity\",{\"_index\":319,\"name\":{\"543\":{},\"585\":{},\"627\":{},\"731\":{},\"845\":{}},\"comment\":{}}],[\"host\",{\"_index\":118,\"name\":{\"169\":{}},\"comment\":{}}],[\"hostelement\",{\"_index\":369,\"name\":{\"672\":{}},\"comment\":{}}],[\"hosttimestampprovider\",{\"_index\":56,\"name\":{\"58\":{}},\"comment\":{}}],[\"iaddpointseventargs\",{\"_index\":437,\"name\":{\"883\":{}},\"comment\":{}}],[\"iaddremovestrokeoptions\",{\"_index\":440,\"name\":{\"887\":{}},\"comment\":{}}],[\"ibeginstrokeeventargs\",{\"_index\":443,\"name\":{\"890\":{}},\"comment\":{}}],[\"ibrush\",{\"_index\":446,\"name\":{\"896\":{}},\"comment\":{}}],[\"iclientinfo\",{\"_index\":140,\"name\":{\"239\":{}},\"comment\":{}}],[\"iclienttimestamp\",{\"_index\":141,\"name\":{\"243\":{}},\"comment\":{}}],[\"icolor\",{\"_index\":451,\"name\":{\"902\":{}},\"comment\":{}}],[\"icontainerruntimesignaler\",{\"_index\":143,\"name\":{\"246\":{}},\"comment\":{}}],[\"id\",{\"_index\":423,\"name\":{\"820\":{},\"947\":{},\"962\":{},\"971\":{}},\"comment\":{}}],[\"idletime\",{\"_index\":414,\"name\":{\"790\":{}},\"comment\":{}}],[\"ievent\",{\"_index\":147,\"name\":{\"250\":{}},\"comment\":{}}],[\"ifluidcontainerinfo\",{\"_index\":149,\"name\":{\"252\":{}},\"comment\":{}}],[\"ifluidtenantinfo\",{\"_index\":153,\"name\":{\"257\":{}},\"comment\":{}}],[\"ifluidturboclient\",{\"_index\":300,\"name\":{\"517\":{}},\"comment\":{}}],[\"ifollowmodepresenceuserdata\",{\"_index\":156,\"name\":{\"260\":{}},\"comment\":{}}],[\"ifollowmodestate\",{\"_index\":159,\"name\":{\"263\":{}},\"comment\":{}}],[\"iliveevent\",{\"_index\":164,\"name\":{\"269\":{}},\"comment\":{}}],[\"iliveeventevents\",{\"_index\":165,\"name\":{\"274\":{}},\"comment\":{}}],[\"ilivefollowmodeevents\",{\"_index\":166,\"name\":{\"275\":{}},\"comment\":{}}],[\"ilivepresenceevents\",{\"_index\":167,\"name\":{\"276\":{}},\"comment\":{}}],[\"iliveshareclientoptions\",{\"_index\":168,\"name\":{\"277\":{}},\"comment\":{}}],[\"ilivesharehost\",{\"_index\":172,\"name\":{\"283\":{}},\"comment\":{}}],[\"ilivesharejoinresults\",{\"_index\":173,\"name\":{\"292\":{}},\"comment\":{}}],[\"ilivestateevents\",{\"_index\":177,\"name\":{\"297\":{}},\"comment\":{}}],[\"ilivetelemetryproperties\",{\"_index\":178,\"name\":{\"298\":{}},\"comment\":{}}],[\"ilivetimerevents\",{\"_index\":181,\"name\":{\"303\":{}},\"comment\":{}}],[\"imediaplayer\",{\"_index\":266,\"name\":{\"432\":{}},\"comment\":{}}],[\"imediaplayerstate\",{\"_index\":274,\"name\":{\"447\":{}},\"comment\":{}}],[\"imediaplayersynchronizerevent\",{\"_index\":278,\"name\":{\"452\":{}},\"comment\":{}}],[\"importraw\",{\"_index\":386,\"name\":{\"693\":{}},\"comment\":{}}],[\"imulticastevent\",{\"_index\":455,\"name\":{\"906\":{}},\"comment\":{}}],[\"indigo\",{\"_index\":522,\"name\":{\"1038\":{}},\"comment\":{}}],[\"initialize\",{\"_index\":70,\"name\":{\"80\":{},\"124\":{},\"145\":{},\"188\":{},\"207\":{},\"354\":{},\"783\":{}},\"comment\":{}}],[\"initializestate\",{\"_index\":63,\"name\":{\"68\":{},\"77\":{},\"110\":{},\"137\":{},\"183\":{},\"202\":{},\"349\":{},\"484\":{},\"778\":{}},\"comment\":{}}],[\"initializingfirsttime\",{\"_index\":95,\"name\":{\"125\":{},\"489\":{},\"784\":{}},\"comment\":{}}],[\"initialobjects\",{\"_index\":294,\"name\":{\"477\":{},\"500\":{},\"513\":{}},\"comment\":{}}],[\"inkingcanvas\",{\"_index\":358,\"name\":{\"623\":{}},\"comment\":{}}],[\"inkingmanager\",{\"_index\":359,\"name\":{\"661\":{}},\"comment\":{}}],[\"inkingtool\",{\"_index\":302,\"name\":{\"522\":{}},\"comment\":{}}],[\"inputfilter\",{\"_index\":391,\"name\":{\"699\":{}},\"comment\":{}}],[\"inputfiltercollection\",{\"_index\":394,\"name\":{\"703\":{}},\"comment\":{}}],[\"inputprovider\",{\"_index\":370,\"name\":{\"673\":{},\"708\":{}},\"comment\":{}}],[\"internaladdpoint\",{\"_index\":337,\"name\":{\"561\":{},\"603\":{},\"642\":{},\"749\":{},\"863\":{}},\"comment\":{}}],[\"internalbeginstroke\",{\"_index\":338,\"name\":{\"562\":{},\"604\":{},\"643\":{},\"750\":{},\"864\":{}},\"comment\":{}}],[\"internalcancelstroke\",{\"_index\":339,\"name\":{\"563\":{},\"605\":{},\"644\":{},\"751\":{},\"865\":{}},\"comment\":{}}],[\"internalendstroke\",{\"_index\":340,\"name\":{\"564\":{},\"606\":{},\"645\":{},\"752\":{},\"866\":{}},\"comment\":{}}],[\"internalrender\",{\"_index\":341,\"name\":{\"565\":{},\"607\":{},\"646\":{},\"753\":{},\"793\":{},\"867\":{}},\"comment\":{}}],[\"intersectswithrectangle\",{\"_index\":434,\"name\":{\"838\":{},\"956\":{},\"984\":{}},\"comment\":{}}],[\"intptimeinfo\",{\"_index\":182,\"name\":{\"304\":{}},\"comment\":{}}],[\"ipoint\",{\"_index\":456,\"name\":{\"909\":{}},\"comment\":{}}],[\"ipointerevent\",{\"_index\":459,\"name\":{\"912\":{}},\"comment\":{}}],[\"ipointermovedeventargs\",{\"_index\":466,\"name\":{\"927\":{}},\"comment\":{}}],[\"ipointermoveevent\",{\"_index\":464,\"name\":{\"919\":{}},\"comment\":{}}],[\"ipointerpoint\",{\"_index\":467,\"name\":{\"929\":{}},\"comment\":{}}],[\"irawstroke\",{\"_index\":468,\"name\":{\"933\":{}},\"comment\":{}}],[\"irect\",{\"_index\":469,\"name\":{\"936\":{}},\"comment\":{}}],[\"iruntimesignaler\",{\"_index\":185,\"name\":{\"307\":{}},\"comment\":{}}],[\"isactive\",{\"_index\":401,\"name\":{\"715\":{},\"808\":{}},\"comment\":{}}],[\"iscursorshared\",{\"_index\":412,\"name\":{\"779\":{}},\"comment\":{}}],[\"isegment\",{\"_index\":474,\"name\":{\"941\":{}},\"comment\":{}}],[\"isfromclient\",{\"_index\":110,\"name\":{\"158\":{}},\"comment\":{}}],[\"isinitialized\",{\"_index\":64,\"name\":{\"69\":{},\"78\":{},\"111\":{},\"138\":{},\"184\":{},\"203\":{},\"350\":{},\"485\":{},\"780\":{}},\"comment\":{}}],[\"islimiting\",{\"_index\":244,\"name\":{\"405\":{}},\"comment\":{}}],[\"islocaluser\",{\"_index\":105,\"name\":{\"152\":{}},\"comment\":{}}],[\"islocalvalue\",{\"_index\":160,\"name\":{\"265\":{}},\"comment\":{}}],[\"isnewer\",{\"_index\":72,\"name\":{\"84\":{}},\"comment\":{}}],[\"ispointerdown\",{\"_index\":465,\"name\":{\"922\":{}},\"comment\":{}}],[\"isrunning\",{\"_index\":57,\"name\":{\"60\":{},\"102\":{},\"233\":{}},\"comment\":{}}],[\"issuspended\",{\"_index\":221,\"name\":{\"366\":{}},\"comment\":{}}],[\"istesting\",{\"_index\":114,\"name\":{\"163\":{},\"506\":{}},\"comment\":{}}],[\"istroke\",{\"_index\":477,\"name\":{\"944\":{}},\"comment\":{}}],[\"istrokecreationoptions\",{\"_index\":478,\"name\":{\"959\":{}},\"comment\":{}}],[\"iterator\",{\"_index\":425,\"name\":{\"823\":{}},\"comment\":{}}],[\"itimerconfig\",{\"_index\":187,\"name\":{\"314\":{}},\"comment\":{}}],[\"itimerconfigdata\",{\"_index\":192,\"name\":{\"320\":{}},\"comment\":{}}],[\"iuserinfo\",{\"_index\":479,\"name\":{\"965\":{}},\"comment\":{}}],[\"iwetstroke\",{\"_index\":481,\"name\":{\"968\":{}},\"comment\":{}}],[\"jitterfilter\",{\"_index\":407,\"name\":{\"723\":{}},\"comment\":{}}],[\"join\",{\"_index\":299,\"name\":{\"516\":{}},\"comment\":{}}],[\"joincontainer\",{\"_index\":115,\"name\":{\"164\":{}},\"comment\":{}}],[\"laserpointer\",{\"_index\":305,\"name\":{\"525\":{},\"537\":{}},\"comment\":{}}],[\"laserpointerbrush\",{\"_index\":371,\"name\":{\"674\":{}},\"comment\":{}}],[\"laserpointercanvas\",{\"_index\":408,\"name\":{\"727\":{}},\"comment\":{}}],[\"lasershadowopacity\",{\"_index\":320,\"name\":{\"544\":{},\"586\":{},\"628\":{},\"732\":{},\"846\":{}},\"comment\":{}}],[\"lavender\",{\"_index\":512,\"name\":{\"1023\":{}},\"comment\":{}}],[\"left\",{\"_index\":471,\"name\":{\"938\":{}},\"comment\":{}}],[\"length\",{\"_index\":424,\"name\":{\"821\":{},\"948\":{},\"972\":{}},\"comment\":{}}],[\"lightblue\",{\"_index\":523,\"name\":{\"1039\":{}},\"comment\":{}}],[\"lightencolor\",{\"_index\":536,\"name\":{\"1060\":{}},\"comment\":{}}],[\"lightgray\",{\"_index\":513,\"name\":{\"1024\":{},\"1040\":{}},\"comment\":{}}],[\"lightgreen\",{\"_index\":514,\"name\":{\"1025\":{},\"1041\":{}},\"comment\":{}}],[\"lime\",{\"_index\":515,\"name\":{\"1026\":{}},\"comment\":{}}],[\"limitlevel\",{\"_index\":245,\"name\":{\"406\":{}},\"comment\":{}}],[\"limitleveltype\",{\"_index\":200,\"name\":{\"333\":{},\"407\":{}},\"comment\":{}}],[\"line\",{\"_index\":306,\"name\":{\"526\":{},\"534\":{}},\"comment\":{}}],[\"linebrush\",{\"_index\":372,\"name\":{\"675\":{}},\"comment\":{}}],[\"lineto\",{\"_index\":342,\"name\":{\"566\":{},\"608\":{},\"647\":{},\"754\":{},\"868\":{}},\"comment\":{}}],[\"livecanvas\",{\"_index\":409,\"name\":{\"769\":{}},\"comment\":{}}],[\"livecursor\",{\"_index\":413,\"name\":{\"787\":{}},\"comment\":{}}],[\"livedataobject\",{\"_index\":62,\"name\":{\"66\":{}},\"comment\":{}}],[\"livedataobjectinitializestate\",{\"_index\":14,\"name\":{\"14\":{}},\"comment\":{}}],[\"liveevent\",{\"_index\":67,\"name\":{\"73\":{}},\"comment\":{}}],[\"liveeventevents\",{\"_index\":19,\"name\":{\"19\":{}},\"comment\":{}}],[\"liveeventlistener\",{\"_index\":196,\"name\":{\"327\":{}},\"comment\":{}}],[\"liveeventscope\",{\"_index\":73,\"name\":{\"85\":{}},\"comment\":{}}],[\"liveeventsource\",{\"_index\":79,\"name\":{\"92\":{}},\"comment\":{}}],[\"liveeventtarget\",{\"_index\":80,\"name\":{\"95\":{}},\"comment\":{}}],[\"liveeventtimer\",{\"_index\":81,\"name\":{\"98\":{}},\"comment\":{}}],[\"livefollowmode\",{\"_index\":84,\"name\":{\"106\":{}},\"comment\":{}}],[\"livefollowmodeevents\",{\"_index\":21,\"name\":{\"21\":{}},\"comment\":{}}],[\"livemediasession\",{\"_index\":209,\"name\":{\"343\":{}},\"comment\":{}}],[\"livemediasessioncoordinator\",{\"_index\":215,\"name\":{\"360\":{}},\"comment\":{}}],[\"livemediasessioncoordinatorsuspension\",{\"_index\":228,\"name\":{\"376\":{}},\"comment\":{}}],[\"livepresence\",{\"_index\":100,\"name\":{\"132\":{}},\"comment\":{}}],[\"livepresenceevents\",{\"_index\":24,\"name\":{\"24\":{}},\"comment\":{}}],[\"livepresenceuser\",{\"_index\":102,\"name\":{\"149\":{}},\"comment\":{}}],[\"liveshareclient\",{\"_index\":111,\"name\":{\"159\":{}},\"comment\":{}}],[\"liveshareruntime\",{\"_index\":116,\"name\":{\"165\":{}},\"comment\":{}}],[\"liveshareturboclient\",{\"_index\":298,\"name\":{\"503\":{}},\"comment\":{}}],[\"livestate\",{\"_index\":123,\"name\":{\"179\":{}},\"comment\":{}}],[\"livestateevents\",{\"_index\":25,\"name\":{\"26\":{}},\"comment\":{}}],[\"livestream\",{\"_index\":254,\"name\":{\"417\":{}},\"comment\":{}}],[\"livetelemetrylogger\",{\"_index\":125,\"name\":{\"192\":{}},\"comment\":{}}],[\"livetimer\",{\"_index\":130,\"name\":{\"198\":{}},\"comment\":{}}],[\"livetimerevents\",{\"_index\":26,\"name\":{\"28\":{}},\"comment\":{}}],[\"load\",{\"_index\":273,\"name\":{\"443\":{}},\"comment\":{}}],[\"local\",{\"_index\":11,\"name\":{\"11\":{},\"425\":{}},\"comment\":{}}],[\"local_mode_test_token\",{\"_index\":138,\"name\":{\"220\":{}},\"comment\":{}}],[\"localclientid\",{\"_index\":363,\"name\":{\"666\":{}},\"comment\":{}}],[\"localtimestampprovider\",{\"_index\":134,\"name\":{\"213\":{}},\"comment\":{}}],[\"localuser\",{\"_index\":85,\"name\":{\"112\":{},\"139\":{}},\"comment\":{}}],[\"logger\",{\"_index\":170,\"name\":{\"280\":{},\"310\":{},\"351\":{}},\"comment\":{}}],[\"magenta\",{\"_index\":495,\"name\":{\"1001\":{}},\"comment\":{}}],[\"maxclients\",{\"_index\":251,\"name\":{\"413\":{}},\"comment\":{}}],[\"maxcontainerlookuptries\",{\"_index\":112,\"name\":{\"161\":{},\"507\":{}},\"comment\":{}}],[\"maxplaybackdrift\",{\"_index\":222,\"name\":{\"367\":{}},\"comment\":{}}],[\"mediaplayersynchronizer\",{\"_index\":231,\"name\":{\"380\":{}},\"comment\":{}}],[\"mediaplayersynchronizerevents\",{\"_index\":203,\"name\":{\"336\":{}},\"comment\":{}}],[\"mediasession\",{\"_index\":232,\"name\":{\"382\":{}},\"comment\":{}}],[\"mediasessionactionthrottler\",{\"_index\":240,\"name\":{\"396\":{}},\"comment\":{}}],[\"mediasessioncoordinatorevents\",{\"_index\":207,\"name\":{\"340\":{}},\"comment\":{}}],[\"mediasessioncoordinatorstate\",{\"_index\":285,\"name\":{\"465\":{}},\"comment\":{}}],[\"mediasessioncoordinatorsuspension\",{\"_index\":281,\"name\":{\"459\":{}},\"comment\":{}}],[\"metadata\",{\"_index\":260,\"name\":{\"426\":{},\"448\":{}},\"comment\":{}}],[\"mode\",{\"_index\":444,\"name\":{\"892\":{},\"973\":{}},\"comment\":{}}],[\"moveto\",{\"_index\":343,\"name\":{\"567\":{},\"609\":{},\"648\":{},\"755\":{},\"869\":{}},\"comment\":{}}],[\"multicastevent\",{\"_index\":418,\"name\":{\"795\":{}},\"comment\":{}}],[\"muted\",{\"_index\":270,\"name\":{\"437\":{}},\"comment\":{}}],[\"name\",{\"_index\":148,\"name\":{\"251\":{},\"272\":{},\"457\":{}},\"comment\":{}}],[\"needed\",{\"_index\":16,\"name\":{\"16\":{}},\"comment\":{}}],[\"next\",{\"_index\":426,\"name\":{\"825\":{}},\"comment\":{}}],[\"notfound\",{\"_index\":5,\"name\":{\"5\":{}},\"comment\":{}}],[\"ntptime\",{\"_index\":183,\"name\":{\"305\":{}},\"comment\":{}}],[\"ntptimeinutc\",{\"_index\":184,\"name\":{\"306\":{}},\"comment\":{}}],[\"numstoipointerpoint\",{\"_index\":344,\"name\":{\"568\":{},\"610\":{},\"649\":{},\"756\":{},\"870\":{}},\"comment\":{}}],[\"objectmanager\",{\"_index\":119,\"name\":{\"170\":{}},\"comment\":{}}],[\"off\",{\"_index\":144,\"name\":{\"247\":{},\"311\":{},\"798\":{},\"907\":{}},\"comment\":{}}],[\"offevent\",{\"_index\":76,\"name\":{\"89\":{}},\"comment\":{}}],[\"offline\",{\"_index\":34,\"name\":{\"36\":{}},\"comment\":{}}],[\"offset\",{\"_index\":324,\"name\":{\"548\":{},\"590\":{},\"632\":{},\"676\":{},\"736\":{},\"850\":{}},\"comment\":{}}],[\"on\",{\"_index\":145,\"name\":{\"248\":{},\"312\":{},\"799\":{},\"908\":{}},\"comment\":{}}],[\"oncreatelivecursor\",{\"_index\":410,\"name\":{\"771\":{}},\"comment\":{}}],[\"onevent\",{\"_index\":77,\"name\":{\"90\":{}},\"comment\":{}}],[\"ongetlocaluserpictureurl\",{\"_index\":411,\"name\":{\"773\":{}},\"comment\":{}}],[\"online\",{\"_index\":35,\"name\":{\"37\":{}},\"comment\":{}}],[\"ontick\",{\"_index\":28,\"name\":{\"30\":{}},\"comment\":{}}],[\"orange\",{\"_index\":516,\"name\":{\"1027\":{},\"1042\":{}},\"comment\":{}}],[\"organizer\",{\"_index\":39,\"name\":{\"41\":{}},\"comment\":{}}],[\"otheruserscount\",{\"_index\":161,\"name\":{\"266\":{}},\"comment\":{}}],[\"paleblue\",{\"_index\":517,\"name\":{\"1028\":{}},\"comment\":{}}],[\"pause\",{\"_index\":132,\"name\":{\"208\":{},\"371\":{},\"390\":{},\"444\":{}},\"comment\":{}}],[\"paused\",{\"_index\":29,\"name\":{\"31\":{},\"438\":{}},\"comment\":{}}],[\"pen\",{\"_index\":307,\"name\":{\"527\":{}},\"comment\":{}}],[\"penbrush\",{\"_index\":373,\"name\":{\"677\":{}},\"comment\":{}}],[\"pencolors\",{\"_index\":519,\"name\":{\"1032\":{}},\"comment\":{}}],[\"pending\",{\"_index\":17,\"name\":{\"17\":{}},\"comment\":{}}],[\"percentage\",{\"_index\":202,\"name\":{\"335\":{}},\"comment\":{}}],[\"persistent\",{\"_index\":315,\"name\":{\"538\":{}},\"comment\":{}}],[\"pictureuri\",{\"_index\":480,\"name\":{\"967\":{}},\"comment\":{}}],[\"pink\",{\"_index\":509,\"name\":{\"1016\":{},\"1043\":{}},\"comment\":{}}],[\"play\",{\"_index\":133,\"name\":{\"209\":{},\"372\":{},\"391\":{},\"445\":{}},\"comment\":{}}],[\"playbackrate\",{\"_index\":271,\"name\":{\"439\":{}},\"comment\":{}}],[\"playbackstate\",{\"_index\":275,\"name\":{\"449\":{}},\"comment\":{}}],[\"played\",{\"_index\":30,\"name\":{\"32\":{}},\"comment\":{}}],[\"player\",{\"_index\":233,\"name\":{\"383\":{}},\"comment\":{}}],[\"plum\",{\"_index\":524,\"name\":{\"1044\":{}},\"comment\":{}}],[\"pointerase\",{\"_index\":387,\"name\":{\"694\":{},\"839\":{},\"957\":{},\"985\":{}},\"comment\":{}}],[\"pointeraser\",{\"_index\":308,\"name\":{\"528\":{}},\"comment\":{}}],[\"pointerdown\",{\"_index\":402,\"name\":{\"716\":{},\"809\":{}},\"comment\":{}}],[\"pointerdownevent\",{\"_index\":396,\"name\":{\"710\":{},\"803\":{}},\"comment\":{}}],[\"pointerenter\",{\"_index\":403,\"name\":{\"717\":{},\"810\":{}},\"comment\":{}}],[\"pointerenterevent\",{\"_index\":397,\"name\":{\"711\":{},\"804\":{}},\"comment\":{}}],[\"pointerinputprovider\",{\"_index\":420,\"name\":{\"800\":{}},\"comment\":{}}],[\"pointerleave\",{\"_index\":404,\"name\":{\"718\":{},\"811\":{}},\"comment\":{}}],[\"pointerleaveevent\",{\"_index\":398,\"name\":{\"712\":{},\"805\":{}},\"comment\":{}}],[\"pointermove\",{\"_index\":405,\"name\":{\"719\":{},\"812\":{}},\"comment\":{}}],[\"pointermovedevent\",{\"_index\":526,\"name\":{\"1050\":{}},\"comment\":{}}],[\"pointermoveevent\",{\"_index\":399,\"name\":{\"713\":{},\"806\":{}},\"comment\":{}}],[\"pointerup\",{\"_index\":406,\"name\":{\"720\":{},\"813\":{}},\"comment\":{}}],[\"pointerupevent\",{\"_index\":400,\"name\":{\"714\":{},\"807\":{}},\"comment\":{}}],[\"points\",{\"_index\":325,\"name\":{\"549\":{},\"591\":{},\"737\":{},\"851\":{},\"885\":{},\"935\":{},\"963\":{}},\"comment\":{}}],[\"position\",{\"_index\":190,\"name\":{\"318\":{},\"322\":{},\"414\":{},\"928\":{}},\"comment\":{}}],[\"positionstate\",{\"_index\":276,\"name\":{\"450\":{}},\"comment\":{}}],[\"positionupdateinterval\",{\"_index\":223,\"name\":{\"368\":{}},\"comment\":{}}],[\"presencechanged\",{\"_index\":22,\"name\":{\"22\":{},\"25\":{}},\"comment\":{}}],[\"presencestate\",{\"_index\":32,\"name\":{\"34\":{}},\"comment\":{}}],[\"presenter\",{\"_index\":40,\"name\":{\"42\":{}},\"comment\":{}}],[\"pressure\",{\"_index\":462,\"name\":{\"915\":{},\"923\":{},\"930\":{}},\"comment\":{}}],[\"purple\",{\"_index\":496,\"name\":{\"1002\":{},\"1045\":{}},\"comment\":{}}],[\"r\",{\"_index\":454,\"name\":{\"905\":{}},\"comment\":{}}],[\"reason\",{\"_index\":252,\"name\":{\"415\":{}},\"comment\":{}}],[\"received\",{\"_index\":20,\"name\":{\"20\":{}},\"comment\":{}}],[\"red\",{\"_index\":497,\"name\":{\"1003\":{},\"1029\":{},\"1046\":{}},\"comment\":{}}],[\"referencepoint\",{\"_index\":317,\"name\":{\"541\":{},\"583\":{},\"625\":{},\"678\":{},\"729\":{},\"843\":{}},\"comment\":{}}],[\"registerclientid\",{\"_index\":48,\"name\":{\"50\":{},\"228\":{},\"290\":{}},\"comment\":{}}],[\"registerobjectclass\",{\"_index\":55,\"name\":{\"57\":{}},\"comment\":{}}],[\"removeeventlistener\",{\"_index\":239,\"name\":{\"392\":{},\"446\":{}},\"comment\":{}}],[\"removefromdom\",{\"_index\":345,\"name\":{\"569\":{},\"611\":{},\"650\":{},\"757\":{},\"871\":{}},\"comment\":{}}],[\"removelayer\",{\"_index\":346,\"name\":{\"570\":{},\"612\":{},\"651\":{},\"758\":{},\"872\":{}},\"comment\":{}}],[\"removestroke\",{\"_index\":388,\"name\":{\"695\":{}},\"comment\":{}}],[\"rendercircle\",{\"_index\":347,\"name\":{\"571\":{},\"613\":{},\"652\":{},\"759\":{},\"873\":{}},\"comment\":{}}],[\"renderedelement\",{\"_index\":415,\"name\":{\"791\":{}},\"comment\":{}}],[\"renderquad\",{\"_index\":348,\"name\":{\"572\":{},\"614\":{},\"653\":{},\"760\":{},\"874\":{}},\"comment\":{}}],[\"renderrectangle\",{\"_index\":349,\"name\":{\"573\":{},\"615\":{},\"654\":{},\"761\":{},\"875\":{}},\"comment\":{}}],[\"rendersasynchronously\",{\"_index\":351,\"name\":{\"575\":{},\"617\":{},\"656\":{},\"763\":{},\"877\":{}},\"comment\":{}}],[\"rendersprogressively\",{\"_index\":352,\"name\":{\"576\":{},\"618\":{},\"764\":{},\"878\":{}},\"comment\":{}}],[\"renderstroke\",{\"_index\":350,\"name\":{\"574\":{},\"616\":{},\"655\":{},\"762\":{},\"876\":{}},\"comment\":{}}],[\"repeat\",{\"_index\":82,\"name\":{\"100\":{}},\"comment\":{}}],[\"repeatedactionthrottler\",{\"_index\":242,\"name\":{\"399\":{}},\"comment\":{}}],[\"repeatinterval\",{\"_index\":243,\"name\":{\"401\":{}},\"comment\":{}}],[\"reset\",{\"_index\":393,\"name\":{\"702\":{},\"707\":{},\"726\":{}},\"comment\":{}}],[\"resize\",{\"_index\":353,\"name\":{\"577\":{},\"619\":{},\"657\":{},\"765\":{},\"879\":{}},\"comment\":{}}],[\"results\",{\"_index\":288,\"name\":{\"470\":{},\"495\":{},\"508\":{}},\"comment\":{}}],[\"retryafter\",{\"_index\":151,\"name\":{\"255\":{}},\"comment\":{}}],[\"right\",{\"_index\":472,\"name\":{\"939\":{}},\"comment\":{}}],[\"roles\",{\"_index\":106,\"name\":{\"153\":{},\"241\":{}},\"comment\":{}}],[\"roleverifier\",{\"_index\":171,\"name\":{\"281\":{}},\"comment\":{}}],[\"rose\",{\"_index\":518,\"name\":{\"1030\":{}},\"comment\":{}}],[\"running\",{\"_index\":191,\"name\":{\"319\":{},\"323\":{}},\"comment\":{}}],[\"scale\",{\"_index\":326,\"name\":{\"550\":{},\"592\":{},\"633\":{},\"679\":{},\"738\":{},\"852\":{}},\"comment\":{}}],[\"schedulerender\",{\"_index\":354,\"name\":{\"578\":{},\"620\":{},\"658\":{},\"766\":{},\"880\":{}},\"comment\":{}}],[\"screentoviewport\",{\"_index\":389,\"name\":{\"696\":{},\"1061\":{}},\"comment\":{}}],[\"seekoffset\",{\"_index\":261,\"name\":{\"427\":{}},\"comment\":{}}],[\"seektime\",{\"_index\":262,\"name\":{\"428\":{}},\"comment\":{}}],[\"seekto\",{\"_index\":225,\"name\":{\"373\":{},\"393\":{}},\"comment\":{}}],[\"send\",{\"_index\":71,\"name\":{\"81\":{}},\"comment\":{}}],[\"senderrorevent\",{\"_index\":126,\"name\":{\"194\":{}},\"comment\":{}}],[\"sendevent\",{\"_index\":78,\"name\":{\"91\":{},\"94\":{},\"97\":{},\"103\":{}},\"comment\":{}}],[\"sendperformanceevent\",{\"_index\":127,\"name\":{\"195\":{}},\"comment\":{}}],[\"sendtelemetryevent\",{\"_index\":128,\"name\":{\"196\":{}},\"comment\":{}}],[\"serialize\",{\"_index\":435,\"name\":{\"840\":{},\"958\":{},\"986\":{}},\"comment\":{}}],[\"serviceendpoint\",{\"_index\":154,\"name\":{\"258\":{}},\"comment\":{}}],[\"services\",{\"_index\":176,\"name\":{\"295\":{}},\"comment\":{}}],[\"set\",{\"_index\":124,\"name\":{\"189\":{}},\"comment\":{}}],[\"setactionhandler\",{\"_index\":212,\"name\":{\"355\":{}},\"comment\":{}}],[\"setaudience\",{\"_index\":49,\"name\":{\"51\":{},\"174\":{}},\"comment\":{}}],[\"setbrush\",{\"_index\":355,\"name\":{\"579\":{},\"621\":{},\"659\":{},\"767\":{},\"881\":{}},\"comment\":{}}],[\"setfluidcontainerid\",{\"_index\":50,\"name\":{\"52\":{},\"229\":{},\"291\":{}},\"comment\":{}}],[\"sethost\",{\"_index\":121,\"name\":{\"175\":{}},\"comment\":{}}],[\"setinputfilters\",{\"_index\":390,\"name\":{\"697\":{}},\"comment\":{}}],[\"setposition\",{\"_index\":417,\"name\":{\"794\":{}},\"comment\":{}}],[\"setrequestplayerstatehandler\",{\"_index\":213,\"name\":{\"356\":{}},\"comment\":{}}],[\"settrack\",{\"_index\":226,\"name\":{\"374\":{},\"394\":{}},\"comment\":{}}],[\"settrackdata\",{\"_index\":227,\"name\":{\"375\":{},\"395\":{}},\"comment\":{}}],[\"shiftkey\",{\"_index\":463,\"name\":{\"916\":{},\"924\":{}},\"comment\":{}}],[\"shouldcreate\",{\"_index\":152,\"name\":{\"256\":{}},\"comment\":{}}],[\"silver\",{\"_index\":498,\"name\":{\"1004\":{}},\"comment\":{}}],[\"skyblue\",{\"_index\":525,\"name\":{\"1047\":{}},\"comment\":{}}],[\"source\",{\"_index\":263,\"name\":{\"429\":{}},\"comment\":{}}],[\"src\",{\"_index\":272,\"name\":{\"440\":{}},\"comment\":{}}],[\"start\",{\"_index\":60,\"name\":{\"64\":{},\"104\":{},\"176\":{},\"210\":{},\"237\":{}},\"comment\":{}}],[\"started\",{\"_index\":31,\"name\":{\"33\":{}},\"comment\":{}}],[\"startlimiting\",{\"_index\":248,\"name\":{\"410\":{}},\"comment\":{}}],[\"startpoint\",{\"_index\":445,\"name\":{\"893\":{}},\"comment\":{}}],[\"startpresenting\",{\"_index\":96,\"name\":{\"126\":{}},\"comment\":{}}],[\"state\",{\"_index\":86,\"name\":{\"113\":{},\"154\":{},\"185\":{}},\"comment\":{}}],[\"statechanged\",{\"_index\":23,\"name\":{\"23\":{},\"27\":{}},\"comment\":{}}],[\"statemap\",{\"_index\":289,\"name\":{\"471\":{},\"496\":{},\"509\":{},\"519\":{}},\"comment\":{}}],[\"statevalue\",{\"_index\":158,\"name\":{\"262\":{}},\"comment\":{}}],[\"stop\",{\"_index\":61,\"name\":{\"65\":{},\"105\":{},\"177\":{},\"238\":{}},\"comment\":{}}],[\"stopfollowing\",{\"_index\":97,\"name\":{\"127\":{}},\"comment\":{}}],[\"stoplimiting\",{\"_index\":249,\"name\":{\"411\":{}},\"comment\":{}}],[\"stoppresenting\",{\"_index\":98,\"name\":{\"128\":{}},\"comment\":{}}],[\"straighten\",{\"_index\":483,\"name\":{\"987\":{}},\"comment\":{}}],[\"stroke\",{\"_index\":422,\"name\":{\"816\":{}},\"comment\":{}}],[\"strokeendstate\",{\"_index\":309,\"name\":{\"529\":{}},\"comment\":{}}],[\"strokeid\",{\"_index\":439,\"name\":{\"886\":{},\"894\":{}},\"comment\":{}}],[\"strokemode\",{\"_index\":311,\"name\":{\"532\":{}},\"comment\":{}}],[\"strokesaddedevent\",{\"_index\":527,\"name\":{\"1051\":{}},\"comment\":{}}],[\"strokesremovedevent\",{\"_index\":528,\"name\":{\"1052\":{}},\"comment\":{}}],[\"stroketype\",{\"_index\":313,\"name\":{\"535\":{}},\"comment\":{}}],[\"submitsignal\",{\"_index\":146,\"name\":{\"249\":{},\"313\":{}},\"comment\":{}}],[\"succeeded\",{\"_index\":18,\"name\":{\"18\":{}},\"comment\":{}}],[\"suspendfollowpresenter\",{\"_index\":12,\"name\":{\"12\":{}},\"comment\":{}}],[\"suspendfollowuser\",{\"_index\":13,\"name\":{\"13\":{}},\"comment\":{}}],[\"suspension\",{\"_index\":264,\"name\":{\"430\":{}},\"comment\":{}}],[\"synchronize\",{\"_index\":214,\"name\":{\"357\":{}},\"comment\":{}}],[\"tenantid\",{\"_index\":155,\"name\":{\"259\":{}},\"comment\":{}}],[\"testlivesharehost\",{\"_index\":135,\"name\":{\"217\":{}},\"comment\":{}}],[\"throttled\",{\"_index\":241,\"name\":{\"398\":{},\"402\":{}},\"comment\":{}}],[\"tickrate\",{\"_index\":131,\"name\":{\"204\":{}},\"comment\":{}}],[\"timestamp\",{\"_index\":142,\"name\":{\"245\":{},\"273\":{},\"302\":{},\"458\":{},\"822\":{},\"949\":{},\"964\":{},\"974\":{}},\"comment\":{}}],[\"timestampprovider\",{\"_index\":120,\"name\":{\"171\":{},\"231\":{},\"282\":{},\"296\":{}},\"comment\":{}}],[\"tip\",{\"_index\":449,\"name\":{\"899\":{}},\"comment\":{}}],[\"tipsize\",{\"_index\":450,\"name\":{\"900\":{}},\"comment\":{}}],[\"to\",{\"_index\":476,\"name\":{\"943\":{}},\"comment\":{}}],[\"tocssrgbacolor\",{\"_index\":537,\"name\":{\"1062\":{}},\"comment\":{}}],[\"tool\",{\"_index\":374,\"name\":{\"680\":{}},\"comment\":{}}],[\"top\",{\"_index\":473,\"name\":{\"940\":{}},\"comment\":{}}],[\"trackdata\",{\"_index\":277,\"name\":{\"451\":{}},\"comment\":{}}],[\"trackidentifier\",{\"_index\":255,\"name\":{\"418\":{}},\"comment\":{}}],[\"triggeraction\",{\"_index\":208,\"name\":{\"342\":{}},\"comment\":{}}],[\"type\",{\"_index\":162,\"name\":{\"267\":{},\"895\":{},\"901\":{},\"975\":{}},\"comment\":{}}],[\"typename\",{\"_index\":68,\"name\":{\"75\":{},\"108\":{},\"134\":{},\"181\":{},\"200\":{},\"345\":{},\"482\":{},\"775\":{}},\"comment\":{}}],[\"update\",{\"_index\":99,\"name\":{\"129\":{},\"146\":{}},\"comment\":{}}],[\"updatesynchronizationstate\",{\"_index\":197,\"name\":{\"329\":{}},\"comment\":{}}],[\"useraction\",{\"_index\":206,\"name\":{\"339\":{}},\"comment\":{}}],[\"userid\",{\"_index\":107,\"name\":{\"155\":{},\"242\":{}},\"comment\":{}}],[\"userinfo\",{\"_index\":416,\"name\":{\"792\":{}},\"comment\":{}}],[\"usermeetingrole\",{\"_index\":36,\"name\":{\"38\":{}},\"comment\":{}}],[\"value\",{\"_index\":163,\"name\":{\"268\":{},\"829\":{}},\"comment\":{}}],[\"verifylocaluserroles\",{\"_index\":65,\"name\":{\"71\":{},\"82\":{},\"130\":{},\"147\":{},\"190\":{},\"211\":{},\"358\":{},\"490\":{},\"785\":{}},\"comment\":{}}],[\"verifyrolesallowed\",{\"_index\":122,\"name\":{\"178\":{}},\"comment\":{}}],[\"viewonly\",{\"_index\":234,\"name\":{\"384\":{}},\"comment\":{}}],[\"viewport\",{\"_index\":375,\"name\":{\"681\":{}},\"comment\":{}}],[\"viewporttoscreen\",{\"_index\":356,\"name\":{\"580\":{},\"622\":{},\"660\":{},\"698\":{},\"768\":{},\"882\":{},\"1063\":{}},\"comment\":{}}],[\"violet\",{\"_index\":499,\"name\":{\"1005\":{}},\"comment\":{}}],[\"volume\",{\"_index\":246,\"name\":{\"408\":{},\"441\":{}},\"comment\":{}}],[\"volumechangeduration\",{\"_index\":247,\"name\":{\"409\":{}},\"comment\":{}}],[\"volumemanager\",{\"_index\":235,\"name\":{\"385\":{},\"403\":{}},\"comment\":{}}],[\"waitpoint\",{\"_index\":229,\"name\":{\"378\":{},\"460\":{}},\"comment\":{}}],[\"waituntilconnected\",{\"_index\":66,\"name\":{\"72\":{},\"83\":{},\"131\":{},\"148\":{},\"191\":{},\"212\":{},\"359\":{},\"491\":{},\"786\":{}},\"comment\":{}}],[\"wetcanvas\",{\"_index\":436,\"name\":{\"841\":{}},\"comment\":{}}],[\"white\",{\"_index\":500,\"name\":{\"1006\":{},\"1048\":{}},\"comment\":{}}],[\"x\",{\"_index\":457,\"name\":{\"910\":{},\"917\":{},\"925\":{},\"931\":{}},\"comment\":{}}],[\"y\",{\"_index\":458,\"name\":{\"911\":{},\"918\":{},\"926\":{},\"932\":{}},\"comment\":{}}],[\"yellow\",{\"_index\":501,\"name\":{\"1007\":{},\"1031\":{},\"1049\":{}},\"comment\":{}}]],\"pipeline\":[]}}"); \ No newline at end of file diff --git a/docs/assets/style.css b/docs/assets/style.css deleted file mode 100644 index 18b4f8fee..000000000 --- a/docs/assets/style.css +++ /dev/null @@ -1,1367 +0,0 @@ -:root { - /* Light */ - --light-color-background: #f2f4f8; - --light-color-background-secondary: #eff0f1; - --light-color-warning-text: #222; - --light-color-background-warning: #e6e600; - --light-color-icon-background: var(--light-color-background); - --light-color-accent: #c5c7c9; - --light-color-active-menu-item: var(--light-color-accent); - --light-color-text: #222; - --light-color-text-aside: #6e6e6e; - --light-color-link: #1f70c2; - - --light-color-ts-project: #b111c9; - --light-color-ts-module: var(--light-color-ts-project); - --light-color-ts-namespace: var(--light-color-ts-project); - --light-color-ts-enum: #7e6f15; - --light-color-ts-enum-member: var(--light-color-ts-enum); - --light-color-ts-variable: #4760ec; - --light-color-ts-function: #572be7; - --light-color-ts-class: #1f70c2; - --light-color-ts-interface: #108024; - --light-color-ts-constructor: var(--light-color-ts-class); - --light-color-ts-property: var(--light-color-ts-variable); - --light-color-ts-method: var(--light-color-ts-function); - --light-color-ts-call-signature: var(--light-color-ts-method); - --light-color-ts-index-signature: var(--light-color-ts-property); - --light-color-ts-constructor-signature: var(--light-color-ts-constructor); - --light-color-ts-parameter: var(--light-color-ts-variable); - /* type literal not included as links will never be generated to it */ - --light-color-ts-type-parameter: var(--light-color-ts-type-alias); - --light-color-ts-accessor: var(--light-color-ts-property); - --light-color-ts-get-signature: var(--light-color-ts-accessor); - --light-color-ts-set-signature: var(--light-color-ts-accessor); - /* object literal not included as it is not used and will be removed in 0.25 */ - --light-color-ts-type-alias: #d51270; - /* reference not included as links will be colored with the kind that it points to */ - - --light-external-icon: url("data:image/svg+xml;utf8,"); - --light-color-scheme: light; - - /* Dark */ - --dark-color-background: #2b2e33; - --dark-color-background-secondary: #1e2024; - --dark-color-background-warning: #bebe00; - --dark-color-warning-text: #222; - --dark-color-icon-background: var(--dark-color-background-secondary); - --dark-color-accent: #9096a2; - --dark-color-active-menu-item: #5d5d6a; - --dark-color-text: #f5f5f5; - --dark-color-text-aside: #dddddd; - --dark-color-link: #00aff4; - - --dark-color-ts-project: #e358ff; - --dark-color-ts-module: var(--dark-color-ts-project); - --dark-color-ts-namespace: var(--dark-color-ts-project); - --dark-color-ts-enum: #f4d93e; - --dark-color-ts-enum-member: var(--dark-color-ts-enum); - --dark-color-ts-variable: #798dff; - --dark-color-ts-function: #a280ff; - --dark-color-ts-class: #8ac4ff; - --dark-color-ts-interface: #6cff87; - --dark-color-ts-constructor: var(--dark-color-ts-class); - --dark-color-ts-property: var(--dark-color-ts-variable); - --dark-color-ts-method: var(--dark-color-ts-function); - --dark-color-ts-call-signature: var(--dark-color-ts-method); - --dark-color-ts-index-signature: var(--dark-color-ts-property); - --dark-color-ts-constructor-signature: var(--dark-color-ts-constructor); - --dark-color-ts-parameter: var(--dark-color-ts-variable); - /* type literal not included as links will never be generated to it */ - --dark-color-ts-type-parameter: var(--dark-color-ts-type-alias); - --dark-color-ts-accessor: var(--dark-color-ts-property); - --dark-color-ts-get-signature: var(--dark-color-ts-accessor); - --dark-color-ts-set-signature: var(--dark-color-ts-accessor); - /* object literal not included as it is not used and will be removed in 0.25 */ - --dark-color-ts-type-alias: #ff6492; - /* reference not included as links will be colored with the kind that it points to */ - - --dark-external-icon: url("data:image/svg+xml;utf8,"); - --dark-color-scheme: dark; -} - -@media (prefers-color-scheme: light) { - :root { - --color-background: var(--light-color-background); - --color-background-secondary: var(--light-color-background-secondary); - --color-background-warning: var(--light-color-background-warning); - --color-warning-text: var(--light-color-warning-text); - --color-icon-background: var(--light-color-icon-background); - --color-accent: var(--light-color-accent); - --color-active-menu-item: var(--light-color-active-menu-item); - --color-text: var(--light-color-text); - --color-text-aside: var(--light-color-text-aside); - --color-link: var(--light-color-link); - - --color-ts-module: var(--light-color-ts-module); - --color-ts-namespace: var(--light-color-ts-namespace); - --color-ts-enum: var(--light-color-ts-enum); - --color-ts-enum-member: var(--light-color-ts-enum-member); - --color-ts-variable: var(--light-color-ts-variable); - --color-ts-function: var(--light-color-ts-function); - --color-ts-class: var(--light-color-ts-class); - --color-ts-interface: var(--light-color-ts-interface); - --color-ts-constructor: var(--light-color-ts-constructor); - --color-ts-property: var(--light-color-ts-property); - --color-ts-method: var(--light-color-ts-method); - --color-ts-call-signature: var(--light-color-ts-call-signature); - --color-ts-index-signature: var(--light-color-ts-index-signature); - --color-ts-constructor-signature: var( - --light-color-ts-constructor-signature - ); - --color-ts-parameter: var(--light-color-ts-parameter); - --color-ts-type-parameter: var(--light-color-ts-type-parameter); - --color-ts-accessor: var(--light-color-ts-accessor); - --color-ts-get-signature: var(--light-color-ts-get-signature); - --color-ts-set-signature: var(--light-color-ts-set-signature); - --color-ts-type-alias: var(--light-color-ts-type-alias); - - --external-icon: var(--light-external-icon); - --color-scheme: var(--light-color-scheme); - } -} - -@media (prefers-color-scheme: dark) { - :root { - --color-background: var(--dark-color-background); - --color-background-secondary: var(--dark-color-background-secondary); - --color-background-warning: var(--dark-color-background-warning); - --color-warning-text: var(--dark-color-warning-text); - --color-icon-background: var(--dark-color-icon-background); - --color-accent: var(--dark-color-accent); - --color-active-menu-item: var(--dark-color-active-menu-item); - --color-text: var(--dark-color-text); - --color-text-aside: var(--dark-color-text-aside); - --color-link: var(--dark-color-link); - - --color-ts-module: var(--dark-color-ts-module); - --color-ts-namespace: var(--dark-color-ts-namespace); - --color-ts-enum: var(--dark-color-ts-enum); - --color-ts-enum-member: var(--dark-color-ts-enum-member); - --color-ts-variable: var(--dark-color-ts-variable); - --color-ts-function: var(--dark-color-ts-function); - --color-ts-class: var(--dark-color-ts-class); - --color-ts-interface: var(--dark-color-ts-interface); - --color-ts-constructor: var(--dark-color-ts-constructor); - --color-ts-property: var(--dark-color-ts-property); - --color-ts-method: var(--dark-color-ts-method); - --color-ts-call-signature: var(--dark-color-ts-call-signature); - --color-ts-index-signature: var(--dark-color-ts-index-signature); - --color-ts-constructor-signature: var( - --dark-color-ts-constructor-signature - ); - --color-ts-parameter: var(--dark-color-ts-parameter); - --color-ts-type-parameter: var(--dark-color-ts-type-parameter); - --color-ts-accessor: var(--dark-color-ts-accessor); - --color-ts-get-signature: var(--dark-color-ts-get-signature); - --color-ts-set-signature: var(--dark-color-ts-set-signature); - --color-ts-type-alias: var(--dark-color-ts-type-alias); - - --external-icon: var(--dark-external-icon); - --color-scheme: var(--dark-color-scheme); - } -} - -html { - color-scheme: var(--color-scheme); -} - -body { - margin: 0; -} - -:root[data-theme="light"] { - --color-background: var(--light-color-background); - --color-background-secondary: var(--light-color-background-secondary); - --color-background-warning: var(--light-color-background-warning); - --color-warning-text: var(--light-color-warning-text); - --color-icon-background: var(--light-color-icon-background); - --color-accent: var(--light-color-accent); - --color-active-menu-item: var(--light-color-active-menu-item); - --color-text: var(--light-color-text); - --color-text-aside: var(--light-color-text-aside); - --color-link: var(--light-color-link); - - --color-ts-module: var(--light-color-ts-module); - --color-ts-namespace: var(--light-color-ts-namespace); - --color-ts-enum: var(--light-color-ts-enum); - --color-ts-enum-member: var(--light-color-ts-enum-member); - --color-ts-variable: var(--light-color-ts-variable); - --color-ts-function: var(--light-color-ts-function); - --color-ts-class: var(--light-color-ts-class); - --color-ts-interface: var(--light-color-ts-interface); - --color-ts-constructor: var(--light-color-ts-constructor); - --color-ts-property: var(--light-color-ts-property); - --color-ts-method: var(--light-color-ts-method); - --color-ts-call-signature: var(--light-color-ts-call-signature); - --color-ts-index-signature: var(--light-color-ts-index-signature); - --color-ts-constructor-signature: var( - --light-color-ts-constructor-signature - ); - --color-ts-parameter: var(--light-color-ts-parameter); - --color-ts-type-parameter: var(--light-color-ts-type-parameter); - --color-ts-accessor: var(--light-color-ts-accessor); - --color-ts-get-signature: var(--light-color-ts-get-signature); - --color-ts-set-signature: var(--light-color-ts-set-signature); - --color-ts-type-alias: var(--light-color-ts-type-alias); - - --external-icon: var(--light-external-icon); - --color-scheme: var(--light-color-scheme); -} - -:root[data-theme="dark"] { - --color-background: var(--dark-color-background); - --color-background-secondary: var(--dark-color-background-secondary); - --color-background-warning: var(--dark-color-background-warning); - --color-warning-text: var(--dark-color-warning-text); - --color-icon-background: var(--dark-color-icon-background); - --color-accent: var(--dark-color-accent); - --color-active-menu-item: var(--dark-color-active-menu-item); - --color-text: var(--dark-color-text); - --color-text-aside: var(--dark-color-text-aside); - --color-link: var(--dark-color-link); - - --color-ts-module: var(--dark-color-ts-module); - --color-ts-namespace: var(--dark-color-ts-namespace); - --color-ts-enum: var(--dark-color-ts-enum); - --color-ts-enum-member: var(--dark-color-ts-enum-member); - --color-ts-variable: var(--dark-color-ts-variable); - --color-ts-function: var(--dark-color-ts-function); - --color-ts-class: var(--dark-color-ts-class); - --color-ts-interface: var(--dark-color-ts-interface); - --color-ts-constructor: var(--dark-color-ts-constructor); - --color-ts-property: var(--dark-color-ts-property); - --color-ts-method: var(--dark-color-ts-method); - --color-ts-call-signature: var(--dark-color-ts-call-signature); - --color-ts-index-signature: var(--dark-color-ts-index-signature); - --color-ts-constructor-signature: var( - --dark-color-ts-constructor-signature - ); - --color-ts-parameter: var(--dark-color-ts-parameter); - --color-ts-type-parameter: var(--dark-color-ts-type-parameter); - --color-ts-accessor: var(--dark-color-ts-accessor); - --color-ts-get-signature: var(--dark-color-ts-get-signature); - --color-ts-set-signature: var(--dark-color-ts-set-signature); - --color-ts-type-alias: var(--dark-color-ts-type-alias); - - --external-icon: var(--dark-external-icon); - --color-scheme: var(--dark-color-scheme); -} - -.always-visible, -.always-visible .tsd-signatures { - display: inherit !important; -} - -h1, -h2, -h3, -h4, -h5, -h6 { - line-height: 1.2; -} - -h1 > a, -h2 > a, -h3 > a, -h4 > a, -h5 > a, -h6 > a { - text-decoration: none; - color: var(--color-text); -} - -h1 { - font-size: 1.875rem; - margin: 0.67rem 0; -} - -h2 { - font-size: 1.5rem; - margin: 0.83rem 0; -} - -h3 { - font-size: 1.25rem; - margin: 1rem 0; -} - -h4 { - font-size: 1.05rem; - margin: 1.33rem 0; -} - -h5 { - font-size: 1rem; - margin: 1.5rem 0; -} - -h6 { - font-size: 0.875rem; - margin: 2.33rem 0; -} - -.uppercase { - text-transform: uppercase; -} - -dl, -menu, -ol, -ul { - margin: 1em 0; -} - -dd { - margin: 0 0 0 40px; -} - -.container { - max-width: 1700px; - padding: 0 2rem; -} - -/* Footer */ -.tsd-generator { - border-top: 1px solid var(--color-accent); - padding-top: 1rem; - padding-bottom: 1rem; - max-height: 3.5rem; -} - -.tsd-generator > p { - margin-top: 0; - margin-bottom: 0; - padding: 0 1rem; -} - -.container-main { - margin: 0 auto; - /* toolbar, footer, margin */ - min-height: calc(100vh - 41px - 56px - 4rem); -} - -@keyframes fade-in { - from { - opacity: 0; - } - to { - opacity: 1; - } -} -@keyframes fade-out { - from { - opacity: 1; - visibility: visible; - } - to { - opacity: 0; - } -} -@keyframes fade-in-delayed { - 0% { - opacity: 0; - } - 33% { - opacity: 0; - } - 100% { - opacity: 1; - } -} -@keyframes fade-out-delayed { - 0% { - opacity: 1; - visibility: visible; - } - 66% { - opacity: 0; - } - 100% { - opacity: 0; - } -} -@keyframes pop-in-from-right { - from { - transform: translate(100%, 0); - } - to { - transform: translate(0, 0); - } -} -@keyframes pop-out-to-right { - from { - transform: translate(0, 0); - visibility: visible; - } - to { - transform: translate(100%, 0); - } -} -body { - background: var(--color-background); - font-family: "Segoe UI", sans-serif; - font-size: 16px; - color: var(--color-text); -} - -a { - color: var(--color-link); - text-decoration: none; -} -a:hover { - text-decoration: underline; -} -a.external[target="_blank"] { - background-image: var(--external-icon); - background-position: top 3px right; - background-repeat: no-repeat; - padding-right: 13px; -} - -code, -pre { - font-family: Menlo, Monaco, Consolas, "Courier New", monospace; - padding: 0.2em; - margin: 0; - font-size: 0.875rem; - border-radius: 0.8em; -} - -pre { - position: relative; - white-space: pre; - white-space: pre-wrap; - word-wrap: break-word; - padding: 10px; - border: 1px solid var(--color-accent); -} -pre code { - padding: 0; - font-size: 100%; -} -pre > button { - position: absolute; - top: 10px; - right: 10px; - opacity: 0; - transition: opacity 0.1s; - box-sizing: border-box; -} -pre:hover > button, -pre > button.visible { - opacity: 1; -} - -blockquote { - margin: 1em 0; - padding-left: 1em; - border-left: 4px solid gray; -} - -.tsd-typography { - line-height: 1.333em; -} -.tsd-typography ul { - list-style: square; - padding: 0 0 0 20px; - margin: 0; -} -.tsd-typography h4, -.tsd-typography .tsd-index-panel h3, -.tsd-index-panel .tsd-typography h3, -.tsd-typography h5, -.tsd-typography h6 { - font-size: 1em; - margin: 0; -} -.tsd-typography h5, -.tsd-typography h6 { - font-weight: normal; -} -.tsd-typography p, -.tsd-typography ul, -.tsd-typography ol { - margin: 1em 0; -} - -.tsd-breadcrumb { - margin: 0; - padding: 0; - color: var(--color-text-aside); -} -.tsd-breadcrumb a { - color: var(--color-text-aside); - text-decoration: none; -} -.tsd-breadcrumb a:hover { - text-decoration: underline; -} -.tsd-breadcrumb li { - display: inline; -} -.tsd-breadcrumb li:after { - content: " / "; -} - -.tsd-comment-tags { - display: flex; - flex-direction: column; -} -dl.tsd-comment-tag-group { - display: flex; - align-items: center; - overflow: hidden; - margin: 0.5em 0; -} -dl.tsd-comment-tag-group dt { - display: flex; - margin-right: 0.5em; - font-size: 0.875em; - font-weight: normal; -} -dl.tsd-comment-tag-group dd { - margin: 0; -} -code.tsd-tag { - padding: 0.25em 0.4em; - border: 0.1em solid var(--color-accent); - margin-right: 0.25em; - font-size: 70%; -} -h1 code.tsd-tag:first-of-type { - margin-left: 0.25em; -} - -dl.tsd-comment-tag-group dd:before, -dl.tsd-comment-tag-group dd:after { - content: " "; -} -dl.tsd-comment-tag-group dd pre, -dl.tsd-comment-tag-group dd:after { - clear: both; -} -dl.tsd-comment-tag-group p { - margin: 0; -} - -.tsd-panel.tsd-comment .lead { - font-size: 1.1em; - line-height: 1.333em; - margin-bottom: 2em; -} -.tsd-panel.tsd-comment .lead:last-child { - margin-bottom: 0; -} - -.tsd-filter-visibility h4 { - font-size: 1rem; - padding-top: 0.75rem; - padding-bottom: 0.5rem; - margin: 0; -} -.tsd-filter-item:not(:last-child) { - margin-bottom: 0.5rem; -} -.tsd-filter-input { - display: flex; - width: fit-content; - width: -moz-fit-content; - align-items: center; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - cursor: pointer; -} -.tsd-filter-input input[type="checkbox"] { - cursor: pointer; - position: absolute; - width: 1.5em; - height: 1.5em; - opacity: 0; -} -.tsd-filter-input input[type="checkbox"]:disabled { - pointer-events: none; -} -.tsd-filter-input svg { - cursor: pointer; - width: 1.5em; - height: 1.5em; - margin-right: 0.5em; - border-radius: 0.33em; - /* Leaving this at full opacity breaks event listeners on Firefox. - Don't remove unless you know what you're doing. */ - opacity: 0.99; -} -.tsd-filter-input input[type="checkbox"]:focus + svg { - transform: scale(0.95); -} -.tsd-filter-input input[type="checkbox"]:focus:not(:focus-visible) + svg { - transform: scale(1); -} -.tsd-checkbox-background { - fill: var(--color-accent); -} -input[type="checkbox"]:checked ~ svg .tsd-checkbox-checkmark { - stroke: var(--color-text); -} -.tsd-filter-input input:disabled ~ svg > .tsd-checkbox-background { - fill: var(--color-background); - stroke: var(--color-accent); - stroke-width: 0.25rem; -} -.tsd-filter-input input:disabled ~ svg > .tsd-checkbox-checkmark { - stroke: var(--color-accent); -} - -.tsd-theme-toggle { - padding-top: 0.75rem; -} -.tsd-theme-toggle > h4 { - display: inline; - vertical-align: middle; - margin-right: 0.75rem; -} - -.tsd-hierarchy { - list-style: square; - margin: 0; -} -.tsd-hierarchy .target { - font-weight: bold; -} - -.tsd-panel-group.tsd-index-group { - margin-bottom: 0; -} -.tsd-index-panel .tsd-index-list { - list-style: none; - line-height: 1.333em; - margin: 0; - padding: 0.25rem 0 0 0; - overflow: hidden; - display: grid; - grid-template-columns: repeat(3, 1fr); - column-gap: 1rem; - grid-template-rows: auto; -} -@media (max-width: 1024px) { - .tsd-index-panel .tsd-index-list { - grid-template-columns: repeat(2, 1fr); - } -} -@media (max-width: 768px) { - .tsd-index-panel .tsd-index-list { - grid-template-columns: repeat(1, 1fr); - } -} -.tsd-index-panel .tsd-index-list li { - -webkit-page-break-inside: avoid; - -moz-page-break-inside: avoid; - -ms-page-break-inside: avoid; - -o-page-break-inside: avoid; - page-break-inside: avoid; -} - -.tsd-flag { - display: inline-block; - padding: 0.25em 0.4em; - border-radius: 4px; - color: var(--color-comment-tag-text); - background-color: var(--color-comment-tag); - text-indent: 0; - font-size: 75%; - line-height: 1; - font-weight: normal; -} - -.tsd-anchor { - position: relative; - top: -100px; -} - -.tsd-member { - position: relative; -} -.tsd-member .tsd-anchor + h3 { - display: flex; - align-items: center; - margin-top: 0; - margin-bottom: 0; - border-bottom: none; -} - -.tsd-navigation.settings { - margin: 1rem 0; -} -.tsd-navigation > a, -.tsd-navigation .tsd-accordion-summary { - width: calc(100% - 0.5rem); -} -.tsd-navigation a, -.tsd-navigation summary > span, -.tsd-page-navigation a { - display: inline-flex; - align-items: center; - padding: 0.25rem; - color: var(--color-text); - text-decoration: none; - box-sizing: border-box; -} -.tsd-navigation a.current, -.tsd-page-navigation a.current { - background: var(--color-active-menu-item); -} -.tsd-navigation a:hover, -.tsd-page-navigation a:hover { - text-decoration: underline; -} -.tsd-navigation ul, -.tsd-page-navigation ul { - margin-top: 0; - margin-bottom: 0; - padding: 0; - list-style: none; -} -.tsd-navigation li, -.tsd-page-navigation li { - padding: 0; - max-width: 100%; -} -.tsd-nested-navigation { - margin-left: 3rem; -} -.tsd-nested-navigation > li > details { - margin-left: -1.5rem; -} -.tsd-small-nested-navigation { - margin-left: 1.5rem; -} -.tsd-small-nested-navigation > li > details { - margin-left: -1.5rem; -} - -.tsd-nested-navigation > li > a, -.tsd-nested-navigation > li > span { - width: calc(100% - 1.75rem - 0.5rem); -} - -.tsd-page-navigation ul { - padding-left: 1.75rem; -} - -#tsd-sidebar-links a { - margin-top: 0; - margin-bottom: 0.5rem; - line-height: 1.25rem; -} -#tsd-sidebar-links a:last-of-type { - margin-bottom: 0; -} - -a.tsd-index-link { - padding: 0.25rem 0 !important; - font-size: 1rem; - line-height: 1.25rem; - display: inline-flex; - align-items: center; - color: var(--color-text); -} -.tsd-accordion-summary { - list-style-type: none; /* hide marker on non-safari */ - outline: none; /* broken on safari, so just hide it */ -} -.tsd-accordion-summary::-webkit-details-marker { - display: none; /* hide marker on safari */ -} -.tsd-accordion-summary, -.tsd-accordion-summary a { - user-select: none; - -moz-user-select: none; - -webkit-user-select: none; - -ms-user-select: none; - - cursor: pointer; -} -.tsd-accordion-summary a { - width: calc(100% - 1.5rem); -} -.tsd-accordion-summary > * { - margin-top: 0; - margin-bottom: 0; - padding-top: 0; - padding-bottom: 0; -} -.tsd-index-accordion .tsd-accordion-summary > svg { - margin-left: 0.25rem; -} -.tsd-index-content > :not(:first-child) { - margin-top: 0.75rem; -} -.tsd-index-heading { - margin-top: 1.5rem; - margin-bottom: 0.75rem; -} - -.tsd-kind-icon { - margin-right: 0.5rem; - width: 1.25rem; - height: 1.25rem; - min-width: 1.25rem; - min-height: 1.25rem; -} -.tsd-kind-icon path { - transform-origin: center; - transform: scale(1.1); -} -.tsd-signature > .tsd-kind-icon { - margin-right: 0.8rem; -} - -.tsd-panel { - margin-bottom: 2.5rem; -} -.tsd-panel.tsd-member { - margin-bottom: 4rem; -} -.tsd-panel:empty { - display: none; -} -.tsd-panel > h1, -.tsd-panel > h2, -.tsd-panel > h3 { - margin: 1.5rem -1.5rem 0.75rem -1.5rem; - padding: 0 1.5rem 0.75rem 1.5rem; -} -.tsd-panel > h1.tsd-before-signature, -.tsd-panel > h2.tsd-before-signature, -.tsd-panel > h3.tsd-before-signature { - margin-bottom: 0; - border-bottom: none; -} - -.tsd-panel-group { - margin: 4rem 0; -} -.tsd-panel-group.tsd-index-group { - margin: 2rem 0; -} -.tsd-panel-group.tsd-index-group details { - margin: 2rem 0; -} - -#tsd-search { - transition: background-color 0.2s; -} -#tsd-search .title { - position: relative; - z-index: 2; -} -#tsd-search .field { - position: absolute; - left: 0; - top: 0; - right: 2.5rem; - height: 100%; -} -#tsd-search .field input { - box-sizing: border-box; - position: relative; - top: -50px; - z-index: 1; - width: 100%; - padding: 0 10px; - opacity: 0; - outline: 0; - border: 0; - background: transparent; - color: var(--color-text); -} -#tsd-search .field label { - position: absolute; - overflow: hidden; - right: -40px; -} -#tsd-search .field input, -#tsd-search .title, -#tsd-toolbar-links a { - transition: opacity 0.2s; -} -#tsd-search .results { - position: absolute; - visibility: hidden; - top: 40px; - width: 100%; - margin: 0; - padding: 0; - list-style: none; - box-shadow: 0 0 4px rgba(0, 0, 0, 0.25); -} -#tsd-search .results li { - padding: 0 10px; - background-color: var(--color-background); -} -#tsd-search .results li:nth-child(even) { - background-color: var(--color-background-secondary); -} -#tsd-search .results li.state { - display: none; -} -#tsd-search .results li.current, -#tsd-search .results li:hover { - background-color: var(--color-accent); -} -#tsd-search .results a { - display: block; -} -#tsd-search .results a:before { - top: 10px; -} -#tsd-search .results span.parent { - color: var(--color-text-aside); - font-weight: normal; -} -#tsd-search.has-focus { - background-color: var(--color-accent); -} -#tsd-search.has-focus .field input { - top: 0; - opacity: 1; -} -#tsd-search.has-focus .title, -#tsd-search.has-focus #tsd-toolbar-links a { - z-index: 0; - opacity: 0; -} -#tsd-search.has-focus .results { - visibility: visible; -} -#tsd-search.loading .results li.state.loading { - display: block; -} -#tsd-search.failure .results li.state.failure { - display: block; -} - -#tsd-toolbar-links { - position: absolute; - top: 0; - right: 2rem; - height: 100%; - display: flex; - align-items: center; - justify-content: flex-end; -} -#tsd-toolbar-links a { - margin-left: 1.5rem; -} -#tsd-toolbar-links a:hover { - text-decoration: underline; -} - -.tsd-signature { - margin: 0 0 1rem 0; - padding: 1rem 0.5rem; - border: 1px solid var(--color-accent); - font-family: Menlo, Monaco, Consolas, "Courier New", monospace; - font-size: 14px; - overflow-x: auto; -} - -.tsd-signature-symbol { - color: var(--color-text-aside); - font-weight: normal; -} - -.tsd-signature-type { - font-style: italic; - font-weight: normal; -} - -.tsd-signatures { - padding: 0; - margin: 0 0 1em 0; - list-style-type: none; -} -.tsd-signatures .tsd-signature { - margin: 0; - border-color: var(--color-accent); - border-width: 1px 0; - transition: background-color 0.1s; -} -.tsd-description .tsd-signatures .tsd-signature { - border-width: 1px; -} - -ul.tsd-parameter-list, -ul.tsd-type-parameter-list { - list-style: square; - margin: 0; - padding-left: 20px; -} -ul.tsd-parameter-list > li.tsd-parameter-signature, -ul.tsd-type-parameter-list > li.tsd-parameter-signature { - list-style: none; - margin-left: -20px; -} -ul.tsd-parameter-list h5, -ul.tsd-type-parameter-list h5 { - font-size: 16px; - margin: 1em 0 0.5em 0; -} -.tsd-sources { - margin-top: 1rem; - font-size: 0.875em; -} -.tsd-sources a { - color: var(--color-text-aside); - text-decoration: underline; -} -.tsd-sources ul { - list-style: none; - padding: 0; -} - -.tsd-page-toolbar { - position: sticky; - z-index: 1; - top: 0; - left: 0; - width: 100%; - color: var(--color-text); - background: var(--color-background-secondary); - border-bottom: 1px var(--color-accent) solid; - transition: transform 0.3s ease-in-out; -} -.tsd-page-toolbar a { - color: var(--color-text); - text-decoration: none; -} -.tsd-page-toolbar a.title { - font-weight: bold; -} -.tsd-page-toolbar a.title:hover { - text-decoration: underline; -} -.tsd-page-toolbar .tsd-toolbar-contents { - display: flex; - justify-content: space-between; - height: 2.5rem; - margin: 0 auto; -} -.tsd-page-toolbar .table-cell { - position: relative; - white-space: nowrap; - line-height: 40px; -} -.tsd-page-toolbar .table-cell:first-child { - width: 100%; -} -.tsd-page-toolbar .tsd-toolbar-icon { - box-sizing: border-box; - line-height: 0; - padding: 12px 0; -} - -.tsd-widget { - display: inline-block; - overflow: hidden; - opacity: 0.8; - height: 40px; - transition: opacity 0.1s, background-color 0.2s; - vertical-align: bottom; - cursor: pointer; -} -.tsd-widget:hover { - opacity: 0.9; -} -.tsd-widget.active { - opacity: 1; - background-color: var(--color-accent); -} -.tsd-widget.no-caption { - width: 40px; -} -.tsd-widget.no-caption:before { - margin: 0; -} - -.tsd-widget.options, -.tsd-widget.menu { - display: none; -} -input[type="checkbox"] + .tsd-widget:before { - background-position: -120px 0; -} -input[type="checkbox"]:checked + .tsd-widget:before { - background-position: -160px 0; -} - -img { - max-width: 100%; -} - -.tsd-anchor-icon { - display: inline-flex; - align-items: center; - margin-left: 0.5rem; - vertical-align: middle; - color: var(--color-text); -} - -.tsd-anchor-icon svg { - width: 1em; - height: 1em; - visibility: hidden; -} - -.tsd-anchor-link:hover > .tsd-anchor-icon svg { - visibility: visible; -} - -.deprecated { - text-decoration: line-through; -} - -.warning { - padding: 1rem; - color: var(--color-warning-text); - background: var(--color-background-warning); -} - -.tsd-kind-project { - color: var(--color-ts-project); -} -.tsd-kind-module { - color: var(--color-ts-module); -} -.tsd-kind-namespace { - color: var(--color-ts-namespace); -} -.tsd-kind-enum { - color: var(--color-ts-enum); -} -.tsd-kind-enum-member { - color: var(--color-ts-enum-member); -} -.tsd-kind-variable { - color: var(--color-ts-variable); -} -.tsd-kind-function { - color: var(--color-ts-function); -} -.tsd-kind-class { - color: var(--color-ts-class); -} -.tsd-kind-interface { - color: var(--color-ts-interface); -} -.tsd-kind-constructor { - color: var(--color-ts-constructor); -} -.tsd-kind-property { - color: var(--color-ts-property); -} -.tsd-kind-method { - color: var(--color-ts-method); -} -.tsd-kind-call-signature { - color: var(--color-ts-call-signature); -} -.tsd-kind-index-signature { - color: var(--color-ts-index-signature); -} -.tsd-kind-constructor-signature { - color: var(--color-ts-constructor-signature); -} -.tsd-kind-parameter { - color: var(--color-ts-parameter); -} -.tsd-kind-type-literal { - color: var(--color-ts-type-literal); -} -.tsd-kind-type-parameter { - color: var(--color-ts-type-parameter); -} -.tsd-kind-accessor { - color: var(--color-ts-accessor); -} -.tsd-kind-get-signature { - color: var(--color-ts-get-signature); -} -.tsd-kind-set-signature { - color: var(--color-ts-set-signature); -} -.tsd-kind-type-alias { - color: var(--color-ts-type-alias); -} - -/* if we have a kind icon, don't color the text by kind */ -.tsd-kind-icon ~ span { - color: var(--color-text); -} - -* { - scrollbar-width: thin; - scrollbar-color: var(--color-accent) var(--color-icon-background); -} - -*::-webkit-scrollbar { - width: 0.75rem; -} - -*::-webkit-scrollbar-track { - background: var(--color-icon-background); -} - -*::-webkit-scrollbar-thumb { - background-color: var(--color-accent); - border-radius: 999rem; - border: 0.25rem solid var(--color-icon-background); -} - -/* mobile */ -@media (max-width: 769px) { - .tsd-widget.options, - .tsd-widget.menu { - display: inline-block; - } - - .container-main { - display: flex; - } - html .col-content { - float: none; - max-width: 100%; - width: 100%; - } - html .col-sidebar { - position: fixed !important; - overflow-y: auto; - -webkit-overflow-scrolling: touch; - z-index: 1024; - top: 0 !important; - bottom: 0 !important; - left: auto !important; - right: 0 !important; - padding: 1.5rem 1.5rem 0 0; - width: 75vw; - visibility: hidden; - background-color: var(--color-background); - transform: translate(100%, 0); - } - html .col-sidebar > *:last-child { - padding-bottom: 20px; - } - html .overlay { - content: ""; - display: block; - position: fixed; - z-index: 1023; - top: 0; - left: 0; - right: 0; - bottom: 0; - background-color: rgba(0, 0, 0, 0.75); - visibility: hidden; - } - - .to-has-menu .overlay { - animation: fade-in 0.4s; - } - - .to-has-menu .col-sidebar { - animation: pop-in-from-right 0.4s; - } - - .from-has-menu .overlay { - animation: fade-out 0.4s; - } - - .from-has-menu .col-sidebar { - animation: pop-out-to-right 0.4s; - } - - .has-menu body { - overflow: hidden; - } - .has-menu .overlay { - visibility: visible; - } - .has-menu .col-sidebar { - visibility: visible; - transform: translate(0, 0); - display: flex; - flex-direction: column; - gap: 1.5rem; - max-height: 100vh; - padding: 1rem 2rem; - } - .has-menu .tsd-navigation { - max-height: 100%; - } -} - -/* one sidebar */ -@media (min-width: 770px) { - .container-main { - display: grid; - grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); - grid-template-areas: "sidebar content"; - margin: 2rem auto; - } - - .col-sidebar { - grid-area: sidebar; - } - .col-content { - grid-area: content; - padding: 0 1rem; - } -} -@media (min-width: 770px) and (max-width: 1399px) { - .col-sidebar { - max-height: calc(100vh - 2rem - 42px); - overflow: auto; - position: sticky; - top: 42px; - padding-top: 1rem; - } - .site-menu { - margin-top: 1rem; - } -} - -/* two sidebars */ -@media (min-width: 1200px) { - .container-main { - grid-template-columns: minmax(0, 1fr) minmax(0, 2.5fr) minmax(0, 20rem); - grid-template-areas: "sidebar content toc"; - } - - .col-sidebar { - display: contents; - } - - .page-menu { - grid-area: toc; - padding-left: 1rem; - } - .site-menu { - grid-area: sidebar; - } - - .site-menu { - margin-top: 1rem 0; - } - - .page-menu, - .site-menu { - max-height: calc(100vh - 2rem - 42px); - overflow: auto; - position: sticky; - top: 42px; - } -} diff --git a/docs/classes/_microsoft_live_share.AzureLiveShareHost.html b/docs/classes/_microsoft_live_share.AzureLiveShareHost.html deleted file mode 100644 index 9174210d2..000000000 --- a/docs/classes/_microsoft_live_share.AzureLiveShareHost.html +++ /dev/null @@ -1,420 +0,0 @@ -AzureLiveShareHost | Microsoft Live Share SDK
-
- -
-
-
- -
-

This host enables using Live Share through your own AzureClient implementation. -This is not intended to be used with LiveShareClient. -We provide no SLA guarantees on this implementation while it is in alpha.

- -

Remarks

To use this API, first pass your ContainerSchema through the getLiveShareContainerSchemaProxy function. -This should be done before calling .getContainer() or createContainer(). -Then, call setAudience() with the IAzureAudience object (in AzureContainerServices) returned by the AzureClient.

-
-
-

Hierarchy

-
    -
  • AzureLiveShareHost
-
-

Implements

-
-
-
-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Will throw not implemented exception. Extend this class and override this function when using with LiveShareClient.

    - -

    See

    ILiveShareHost.getFluidToken

    -
    -
    -

    Parameters

    -
      -
    • -
      Optional containerId: string
    -

    Returns Promise<string>

-
- -
-
- -
-
- -
    - -
  • -

    This function should be called immediately after getting audience from AzureClient.

    -
    -
    -

    Parameters

    -
      -
    • -
      audience: IAzureAudience
      -

      Azure Audience

      -
    -

    Returns void

-
- -
-
- -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share.DynamicObjectRegistry.html b/docs/classes/_microsoft_live_share.DynamicObjectRegistry.html deleted file mode 100644 index f7f8452f4..000000000 --- a/docs/classes/_microsoft_live_share.DynamicObjectRegistry.html +++ /dev/null @@ -1,282 +0,0 @@ -DynamicObjectRegistry | Microsoft Live Share SDK
-
- -
-
-
- -
-

Static registry class for loadable projects for use in frameworks like @microsoft/live-share-turbo. All Live Share packages and extension -frameworks (e.g., LiveMediaSession in our media package) will register their classes from within their main files. Goal of this class is for -all Live Share packages that a developer has installed will be registered as available dynamic objects without the core package needing to be -aware of what every DDS is.

-
-
-

Hierarchy

-
    -
  • DynamicObjectRegistry
-
-
-
- -
-
-

Constructors

-
-
-

Accessors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Accessors

-
- -
-
-

Methods

-
- -
    - -
  • -

    Static method to register a new dynamic loadable object class.

    - -

    Remarks

    Duplicate classes will be ignored.

    -
    -
    -

    Parameters

    -
      -
    • -
      loadableObjectClass: LoadableObjectClass<any>
      -

      the Fluid loadable object class to register

      -
    • -
    • -
      typeName: string
    -

    Returns void

-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share.HostTimestampProvider.html b/docs/classes/_microsoft_live_share.HostTimestampProvider.html deleted file mode 100644 index 8d8630604..000000000 --- a/docs/classes/_microsoft_live_share.HostTimestampProvider.html +++ /dev/null @@ -1,336 +0,0 @@ -HostTimestampProvider | Microsoft Live Share SDK
-
- -
-
-
- -
-

Timestamp Provider that calls the Live Share Host to lookup the current time.

-
-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
-
-

Accessors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Accessors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share.LiveDataObject.html b/docs/classes/_microsoft_live_share.LiveDataObject.html deleted file mode 100644 index ba3bac3bd..000000000 --- a/docs/classes/_microsoft_live_share.LiveDataObject.html +++ /dev/null @@ -1,362 +0,0 @@ -LiveDataObject | Microsoft Live Share SDK
-
- -
-
-
-
- -

Class LiveDataObject<I>Abstract

-
-

Extends Fluid's DataObject class. Intended for use with Live Share custom DDS's that rely on a ILiveShareHost.

-
-
-

Type Parameters

-
    -
  • -

    I extends DataObjectTypes = DataObjectTypes

-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Accessors

-
- -
-
- -
-
-

Methods

-
- -
    - -
  • -

    Get the client info for a given clientId

    -
    -
    -

    Parameters

    -
      -
    • -
      clientId: string
      -

      Fluid clientId we are requesting user info for

      -
    -

    Returns Promise<undefined | IClientInfo>

    IClientInfo object if the user is known, otherwise it will return undefined

    -
-
- -
-
- -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share.LiveEvent.html b/docs/classes/_microsoft_live_share.LiveEvent.html deleted file mode 100644 index 475fc6f1c..000000000 --- a/docs/classes/_microsoft_live_share.LiveEvent.html +++ /dev/null @@ -1,479 +0,0 @@ -LiveEvent | Microsoft Live Share SDK
-
- -
-
-
- -
-

Live fluid object that broadcasts an event to other clients and a set of static event -related helpers.

-

remarks

Applications should call on('received', (evt, local) => {}) to listen for local events sent -and remote events received. Events aren't guaranteed to be delivered so you should limit their -use to sending events you're ok with potentially being missed. Reactions are a good use case for -LiveEvents. Use something like the LiveState class when syncing state.

-
-
-

Type Parameters

-
    -
  • -

    TEvent = any

    -

    Type of event to broadcast.

    -
-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
-
-

Properties

-
-
-

Accessors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Properties

-
- -
TypeName: "@microsoft/live-share:LiveEvent" = ...
-

The objects fluid type/name.

-
-
- -
factory: DataObjectFactory<LiveEvent<any>, DataObjectTypes> = ...
-

The objects fluid type factory.

-
-
-

Accessors

-
- -
-
- -
-
-

Methods

-
- -
-
- -
    - -
  • -

    Initialize the object to begin sending/receiving events through this DDS.

    - -

    Remarks

    You should register received event listeners before calling this function to ensure no incoming events are missed. -received events will not be emitted until after this function is called.

    - -

    Throws

    error when .initialize() has already been called for this class instance.

    -
    -
    -

    Parameters

    -
      -
    • -
      Optional allowedRoles: UserMeetingRole[]
      -

      Optional. List of roles allowed to send events.

      -
    -

    Returns Promise<void>

    a void promise that resolves once complete.

    -
-
- -
    - -
  • -

    Broadcasts an event to all other clients.

    - -

    Remarks

    The event will be queued for delivery if the client isn't currently connected.

    - -

    Throws

    error if initialization has not yet succeeded.

    - -

    Throws

    error if the local user does not have the required roles defined through the allowedRoles prop in .initialize().

    -
    -
    -

    Parameters

    -
      -
    • -
      evt: TEvent
      -

      Event to send. If omitted, an event will still be sent but it won't include any custom event data.

      -
    -

    Returns Promise<ILiveEvent<TEvent>>

    A promise with the full event object that was sent, including the timestamp of when the event was sent and the clientId if known. -The clientId will be undefined if the client is disconnected at time of delivery.

    -
-
- -
-
- -
-
- -
    - -
  • -

    Returns true if a received event is newer then the current event.

    - -

    Remarks

    Used when building new Live objects to process state change events. The isNewer() -method implements an algorithm that deals with conflicting events that have the same timestamp -and older events that should have debounced the current event.

    -
      -
    • When the received event has the same timestamp as the current event, each events clientId -will be used as a tie breaker. The clientId containing the lower sort order wins any ties.
    • -
    • Older events are generally ignored unless a debounce period is specified. An older event -that should have debounced the current event will be considered newer.
    • -
    -

    The algorithm employed by isNewer() helps ensure that all clients will eventually reach a -consistent state with one other.

    -
    -
    -

    Parameters

    -
      -
    • -
      current: undefined | IClientTimestamp
      -

      Current event to compare received event against.

      -
    • -
    • -
      received: IClientTimestamp
      -

      Received event.

      -
    • -
    • -
      debouncePeriod: number = 0
      -

      Optional. Time in milliseconds to ignore any new events for. Defaults to 0 ms.

      -
    -

    Returns boolean

    True if the received event is newer then the current event and should replace the current one.

    -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share.LiveEventScope.html b/docs/classes/_microsoft_live_share.LiveEventScope.html deleted file mode 100644 index 03f8e9c57..000000000 --- a/docs/classes/_microsoft_live_share.LiveEventScope.html +++ /dev/null @@ -1,402 +0,0 @@ -LiveEventScope | Microsoft Live Share SDK
-
- -
-
-
- -
-

Object responsible for sending and receiving live share events.

- -

Remarks

Live objects send and receive events using an event scope. Event scopes can be restricted -to only receive events from clients with specific roles. Any events that are received from -clients without an allowed role type will be ignored.

-

Event scopes are isolated on a per Fluid object basis. That means that two different Fluid -objects using the same event names don't have to worry about collisions. Two event scopes -within the same Fluid object, however, don't have any isolation. You can use multiple event -scopes within the same FLuid object, you just need to be careful that they send different -events.

-
-
-

Hierarchy

-
    -
  • TypedEventEmitter<IErrorEvent> -
      -
    • LiveEventScope
-
-
-
- -
-
-

Constructors

-
-
-

Accessors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Accessors

-
- -
-
- -
-
-

Methods

-
- -
-
- -
-
- -
    - -
  • -

    Sends an event to other event scope instances for the Fluid object.

    -
    -
    -

    Type Parameters

    -
      -
    • -

      TEvent

      -

      Type of event to send.

      -
    -
    -

    Parameters

    -
      -
    • -
      eventName: string
      -

      Name of the event to send.

      -
    • -
    • -
      evt: TEvent
      -

      Optional. Partial event object to send. The ILiveEvent.name, -ILiveEvent.timestamp, and ILiveEvent.clientId -fields will be automatically populated prior to sending.

      -
    -

    Returns Promise<ILiveEvent<TEvent>>

    The full event, including ILiveEvent.name, -ILiveEvent.timestamp, and ILiveEvent.clientId fields if known.

    -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share.LiveEventSource.html b/docs/classes/_microsoft_live_share.LiveEventSource.html deleted file mode 100644 index 99f96bb5d..000000000 --- a/docs/classes/_microsoft_live_share.LiveEventSource.html +++ /dev/null @@ -1,295 +0,0 @@ -LiveEventSource | Microsoft Live Share SDK
-
- -
-
-
- -
-

Broadcasts live share events to all clients and can be received by an LiveEventTarget.

- -

Remarks

Live objects won't typically create an LiveEventSource directly. They will, instead, -create an LiveEventTarget class, which can both send & receive events.

-
-
-

Type Parameters

-
    -
  • -

    TEvent

    -

    Type of event to broadcast.

    -
-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
    - -
  • -

    Broadcasts an event to any listening LiveEventTarget instances.

    -
    -
    -

    Parameters

    -
      -
    • -
      evt: TEvent
      -

      Optional. Partial event object to send. The ILiveEvent.name, -ILiveEvent.timestamp, and ILiveEvent.clientId -fields will be automatically populated prior to sending.

      -
    -

    Returns Promise<ILiveEvent<TEvent>>

    The full event, including ILiveEvent.name, -ILiveEvent.timestamp, and ILiveEvent.clientId fields if known.

    -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share.LiveEventTarget.html b/docs/classes/_microsoft_live_share.LiveEventTarget.html deleted file mode 100644 index af1807a3e..000000000 --- a/docs/classes/_microsoft_live_share.LiveEventTarget.html +++ /dev/null @@ -1,301 +0,0 @@ -LiveEventTarget | Microsoft Live Share SDK
-
- -
-
-
- -
-

Receives events broadcast by an LiveEventSource.

- -

Remarks

All live event targets are also sources. This simplifies the programming model for -live event object by letting them create a single object thats capable of broadcasting -events to other instances of itself.

-
-
-

Type Parameters

-
    -
  • -

    TEvent

    -

    Type of event to broadcast.

    -
-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
    - -
  • -

    Broadcasts an event to any listening LiveEventTarget instances.

    -
    -
    -

    Parameters

    -
      -
    • -
      evt: TEvent
      -

      Optional. Partial event object to send. The ILiveEvent.name, -ILiveEvent.timestamp, and ILiveEvent.clientId -fields will be automatically populated prior to sending.

      -
    -

    Returns Promise<ILiveEvent<TEvent>>

    The full event, including ILiveEvent.name, -ILiveEvent.timestamp, and ILiveEvent.clientId fields if known.

    -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share.LiveEventTimer.html b/docs/classes/_microsoft_live_share.LiveEventTimer.html deleted file mode 100644 index 21eb8891b..000000000 --- a/docs/classes/_microsoft_live_share.LiveEventTimer.html +++ /dev/null @@ -1,365 +0,0 @@ -LiveEventTimer | Microsoft Live Share SDK
-
- -
-
-
- -
-

Periodically broadcasts an event to listening LiveEventTarget instances.

-
-
-

Type Parameters

-
    -
  • -

    T extends object = object

-
-

Hierarchy

-
    -
  • LiveEventTimer
-
-
-
- -
-
-

Constructors

-
-
-

Properties

-
-
-

Accessors

-
-
-

Methods

-
-
-

Constructors

-
- -
    - -
  • -

    Creates a new LiveEventTimer instance. @param eventSource Event source that will be used to emit events. @param createEvent Function used to construct an event to send. This will be called at regular intervals prior to sending an event. @param delay Period to delay for in milliseconds. @param repeat Optional. If true the timer will repeat once start` is called, otherwise a single event will be sent after the delay. Defaults to false.

    -
    -
    -

    Type Parameters

    -
      -
    • -

      T extends object = object

    -
    -

    Parameters

    -
      -
    • -
      eventSource: LiveEventSource<T>
    • -
    • -
      createEvent: (() => T)
      -
        -
      • -
          -
        • (): T
        • -
        • -

          Returns T

    • -
    • -
      delay: number
    • -
    • -
      repeat: boolean = false
    -

    Returns LiveEventTimer<T>

-
-

Properties

-
- -
repeat: boolean
-

If true the event will automatically repeat at an interval specified by the delay.

-
-
-

Accessors

-
- -
-
- -
-
-

Methods

-
- -
    - -
  • -

    Immediately sends an event.

    - -

    Remarks

    The createEvent callback to construct the event is called but does not impact any pending -timeouts. Call start after calling sendEvent if you'd like to skip the next timer -interval.

    -
    -

    Returns Promise<ILiveEvent<T>>

-
- -
-
- -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share.LiveFollowMode.html b/docs/classes/_microsoft_live_share.LiveFollowMode.html deleted file mode 100644 index 249423182..000000000 --- a/docs/classes/_microsoft_live_share.LiveFollowMode.html +++ /dev/null @@ -1,705 +0,0 @@ -LiveFollowMode | Microsoft Live Share SDK
-
- -
-
-
-
- -

Class LiveFollowMode<TData>Beta

-
-

Live object that allows users to present and/or follow other users. -Provides a state value, which reflects the relevant value to reference (e.g., the presenting user's state value).

-
-
-

Type Parameters

-
    -
  • -

    TData = any

    -

    Type of data value to share with clients for each user (e.g., the user's camera position in a 3D scene).

    -
-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Properties

-
- -
TypeName: "@microsoft/live-share:LiveFollowMode" = ...
-

The objects fluid type/name.

-
-
- -
factory: DataObjectFactory<LiveFollowMode<any>, DataObjectTypes> = ...
-

The objects fluid type factory.

-
-
-

Accessors

-
- -
-
- -
-
- -
-
- -
-
-

Methods

-
- -
    - -
  • -

    Temporarily stop following presenter/follower.

    - -

    Throws

    error if initialization has not yet succeeded.

    -
    -

    Returns Promise<void>

    a void promise once the operation succeeds.

    -
-
- -
-
- -
    - -
  • -

    Resume following presenter/follower.

    - -

    Throws

    error if initialization has not yet succeeded.

    -
    -

    Returns Promise<void>

    a void promise once the operation succeeds.

    -
-
- -
    - -
  • -

    Follows another user in the session.

    - -

    Remarks

    If another user is presenting, state will not reflect following this user until there is no longer a presenter.

    - -

    Throws

    error if initialization has not yet succeeded.

    - -

    Throws

    error if attempting to follow a user that is not recognized by this object's LivePresence instance.

    - -

    Throws

    error if the userId provided is equal to the local user's userId.

    -
    -
    -

    Parameters

    -
      -
    • -
      userId: string
      -

      the userId for the user to follow.

      -
    -

    Returns Promise<void>

    a void promise that resolves once the event has been sent to the server.

    -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
    - -
  • -

    hasInitialized is run by each client as they load the DataObject. Here we use it to initialize the -task manager, listen for task assignments, and listen for changes to the dynamic objects map.

    -
    -

    Returns Promise<void>

-
- -
    - -
  • -

    Initialize the object to begin sending/receiving state updates through this DDS.

    - -

    Throws

    error when .initialize() has already been called for this class instance.

    - -

    Throws

    fatal error when .initialize() has already been called for an object of same id but with a different class instance. -This is most common when using dynamic objects through Fluid.

    -
    -
    -

    Parameters

    -
      -
    • -
      initialState: TData
      -

      Initial state value

      -
    • -
    • -
      Optional allowedRoles: UserMeetingRole[]
      -

      Optional. List of roles allowed to make state changes.

      -
    -

    Returns Promise<void>

    a void promise that resolves once complete

    -
-
- -
    - -
  • -

    initializingFirstTime is run only once by the first client to create the DataObject. Here we use it to -initialize the state of the DataObject.

    -
    -

    Returns Promise<void>

-
- -
    - -
  • -

    Start presenting the local user's state.

    - -

    Remarks

    If another user is already presenting, the local user will take control of presenting from the previous presenter. -To update the local user's state that both the local and remote users will reference, use the update function. -This API will override any followingUserId value that was set through followUser until presenting has stopped. -To stop presenting, use the stopPresenting API.

    - -

    Throws

    error if initialization has not yet succeeded.

    - -

    Throws

    error if the local user is already the presenter.

    - -

    Throws

    error if the local user does not have the required roles to present.

    -
    -

    Returns Promise<void>

    a void promise that resolves once the event has been sent to the server.

    -
-
- -
    - -
  • -

    Stop following the currently following user.

    - -

    Throws

    error if initialization has not yet succeeded.

    - -

    Throws

    error if the user is not already following another user.

    -
    -

    Returns Promise<void>

    a void promise that resolves once the event has been sent to the server.

    -
-
- -
    - -
  • -

    Stop presenting the presenting user's current state.

    - -

    Remarks

    This API allows any user with valid roles to cancel presenting, though we generally recommend only allowing the active presenter to do so. -To start presenting, use the startPresenting API.

    - -

    Throws

    error if initialization has not yet succeeded.

    - -

    Throws

    error if the local user does not have the required roles to stop presenting.

    -
    -

    Returns Promise<void>

    a void promise that resolves once the event has been sent to the server.

    -
-
- -
    - -
  • -

    Broadcast a new custom data value for the local user's current state.

    - -

    Remarks

    Each user has their own state value, though it will differ from what is shown in state depending on the value of FollowModeType. -Will cause the user to become out of sync if another user is presenting or the local user is following another user. -To see each user's state, use the getUsers API, or listen to "presenceChanged" updates.

    - -

    Throws

    error if initialization has not yet succeeded.

    -
    -
    -

    Parameters

    -
      -
    • -
      newValue: TData
      -

      the state value for the local user's presence record.

      -
    -

    Returns Promise<void>

    a void promise that resolves once the update event has been sent to the server.

    -
-
- -
-
- -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share.LivePresence.html b/docs/classes/_microsoft_live_share.LivePresence.html deleted file mode 100644 index 2b3afcb32..000000000 --- a/docs/classes/_microsoft_live_share.LivePresence.html +++ /dev/null @@ -1,552 +0,0 @@ -LivePresence | Microsoft Live Share SDK
-
- -
-
-
- -
-

Live fluid object that synchronizes presence information for the user with other clients.

-
-
-

Type Parameters

-
    -
  • -

    TData extends object = object

    -

    Type of data object to share with clients.

    -
-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Properties

-
- -
TypeName: "@microsoft/live-share:LivePresence" = ...
-

The objects fluid type/name.

-
-
- -
factory: DataObjectFactory<LivePresence<object>, DataObjectTypes> = ...
-

The objects fluid type factory.

-
-
-

Accessors

-
- -
    -
  • get expirationPeriod(): number
  • -
  • -

    Number of seconds without a presence update before a remote user is considered offline.

    - -

    Remarks

    Defaults to a value of 20 seconds. The minimum value is 0.1 seconds for testing purposes.

    -
    -

    Returns number

  • -
  • set expirationPeriod(value): void
  • -
  • -
    -

    Parameters

    -
      -
    • -
      value: number
    -

    Returns void

-
- -
-
- -
-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Returns the current presence info for a specific client ID.

    -
    -
    -

    Parameters

    -
      -
    • -
      clientId: string
      -

      The ID of the client to retrieve.

      -
    -

    Returns undefined | LivePresenceUser<TData>

    The current presence information for the client if they've connected to the space.

    -
-
- -
-
- -
    - -
  • -

    Initialize the object to begin sending/receiving presence updates through this DDS.

    - -

    Throws

    error when .initialize() has already been called for this class instance.

    - -

    Throws

    fatal error when .initialize() has already been called for an object of same id but with a different class instance. -This is most common when using dynamic objects through Fluid.

    -
    -
    -

    Parameters

    -
      -
    • -
      Optional data: TData
      -

      Optional. Custom data object to share. A deep copy of the data object is saved to avoid any accidental modifications.

      -
    • -
    • -
      state: PresenceState = PresenceState.online
      -

      Optional. Initial presence state. Defaults to PresenceState.online.

      -
    • -
    • -
      Optional allowedRoles: UserMeetingRole[]
      -

      Optional. List of roles allowed to emit presence changes.

      -
    -

    Returns Promise<void>

    a void promise that resolves once complete.

    -
-
- -
    - -
  • -

    Updates the local user's presence shared data object and/or state.

    - -

    Remarks

    This will trigger the immediate broadcast of the users presence to all other clients.

    - -

    Throws

    error if initialization has not yet succeeded.

    - -

    Throws

    error if the local user does not have the required roles defined through the allowedRoles prop in .initialize().

    -
    -
    -

    Parameters

    -
      -
    • -
      Optional data: TData
      -

      Optional. Data object to change. A deep copy of the data object is saved to avoid any future changes.

      -
    • -
    • -
      Optional state: PresenceState
      -

      Optional. Presence state to change.

      -
    -

    Returns Promise<void>

    a void promise that resolves once the update event has been sent to the server.

    -
-
- -
-
- -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share.LivePresenceUser.html b/docs/classes/_microsoft_live_share.LivePresenceUser.html deleted file mode 100644 index 009953022..000000000 --- a/docs/classes/_microsoft_live_share.LivePresenceUser.html +++ /dev/null @@ -1,361 +0,0 @@ -LivePresenceUser | Microsoft Live Share SDK
-
- -
-
-
- -
-

A user that presence is being tracked for.

-
-
-

Type Parameters

-
    -
  • -

    TData = object

-
-

Hierarchy

-
    -
  • LivePresenceUser
-
-
-
- -
-
-

Accessors

-
- -
    -
  • get data(): undefined | TData
  • -
  • -

    Optional data shared by the user. Returns data from connection with most recent event. -Client connection specific data is available from each connection.

    -
    -

    Returns undefined | TData

-
- -
-
- -
-
- -
-
- -
-
- -
-
-

Methods

-
- -
-
- -
-
- -
    - -
  • -

    Returns true if the presence object is from the specified client.

    -
    -
    -

    Parameters

    -
      -
    • -
      clientId: string
      -

      The ID of the client to lookup.

      -
    -

    Returns boolean

-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share.LiveShareClient.html b/docs/classes/_microsoft_live_share.LiveShareClient.html deleted file mode 100644 index 4d2f9d29b..000000000 --- a/docs/classes/_microsoft_live_share.LiveShareClient.html +++ /dev/null @@ -1,355 +0,0 @@ -LiveShareClient | Microsoft Live Share SDK
-
- -
-
-
- -
-

Client used to connect to fluid containers within a Microsoft Teams context.

-
-
-

Hierarchy

-
    -
  • LiveShareClient
-
-
-
- -
-
-

Constructors

-
-
-

Properties

-
-
-

Accessors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Properties

-
- -
maxContainerLookupTries: number = 3
-

Number of times the client should attempt to get the ID of the container to join for the -current context.

-
-
-

Accessors

-
- -
    -
  • get canSendBackgroundUpdates(): boolean
  • -
  • -

    Setting for whether LiveDataObject instances using LiveObjectSynchronizer can send background updates. -Default value is true.

    - -

    Remarks

    This is useful for scenarios where there are a large number of participants in a session, since service performance degrades as more socket connections are opened. -Intended for use when a small number of users are intended to be "in control", such as the LiveFollowMode class's startPresenting() feature. -There should always be at least one user in the session that has canSendBackgroundUpdates set to true. -Set to true when the user is eligible to send background updates (e.g., "in control"), or false when that user is not in control. -This setting will not prevent the local user from explicitly changing the state of objects using LiveObjectSynchronizer, such as .set() in LiveState. -Impacts background updates of LiveState, LivePresence, LiveTimer, and LiveFollowMode.

    -
    -

    Returns boolean

  • -
  • set canSendBackgroundUpdates(value): void
  • -
  • -
    -

    Parameters

    -
      -
    • -
      value: boolean
    -

    Returns void

-
- -
-
-

Methods

-
- -
    - -
  • -

    Connects to the fluid container for the current teams context.

    - -

    Remarks

    The first client joining the container will create the container resulting in the -onContainerFirstCreated callback being called. This callback can be used to set the initial -state of of the containers object prior to the container being attached.

    -
    -
    -

    Parameters

    -
      -
    • -
      fluidContainerSchema: ContainerSchema
      -

      Fluid objects to create.

      -
    • -
    • -
      Optional onContainerFirstCreated: ((container) => void)
      -

      Optional. Callback that's called when the container is first created.

      -
      -
        -
      • -
          -
        • (container): void
        • -
        • -
          -

          Parameters

          -
            -
          • -
            container: IFluidContainer
          -

          Returns void

    -

    Returns Promise<ILiveShareJoinResults>

    the results of join container.

    -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share.LiveShareRuntime.html b/docs/classes/_microsoft_live_share.LiveShareRuntime.html deleted file mode 100644 index 978a39229..000000000 --- a/docs/classes/_microsoft_live_share.LiveShareRuntime.html +++ /dev/null @@ -1,463 +0,0 @@ -LiveShareRuntime | Microsoft Live Share SDK
-
- -
-
-
- -
-

Runtime for LiveDataObject, which is used to do things like validate roles, get a timestamp

-
-
-

Hierarchy

-
    -
  • LiveShareRuntime
-
-
-
- -
-
-

Constructors

-
- -
-
-

Properties

-
- -
_containerRuntime?: IContainerRuntimeSignaler
-
-

Accessors

-
- -
    -
  • get canSendBackgroundUpdates(): boolean
  • -
  • -

    Setting for whether LiveDataObject instances using LiveObjectSynchronizer can send background updates. -Default value is true.

    - -

    Remarks

    This is useful for scenarios where there are a large number of participants in a session, since service performance degrades as more socket connections are opened. -Intended for use when a small number of users are intended to be "in control", such as the LiveFollowMode class's startPresenting() feature. -There should always be at least one user in the session that has canSendBackgroundUpdates set to true. -Set to true when the user is eligible to send background updates (e.g., "in control"), or false when that user is not in control. -This setting will not prevent the local user from explicitly changing the state of objects using LiveObjectSynchronizer, such as .set() in LiveState. -Impacts background updates of LiveState, LivePresence, LiveTimer, and LiveFollowMode.

    -
    -

    Returns boolean

  • -
  • set canSendBackgroundUpdates(value): void
  • -
  • -
    -

    Parameters

    -
      -
    • -
      value: boolean
    -

    Returns void

-
- -
-
- -
-
- -
-
-

Methods

-
- -
    - -
  • -

    Get the client info for a given clientId

    -
    -
    -

    Parameters

    -
      -
    • -
      clientId: string
      -

      Fluid clientId we are requesting user info for

      -
    -

    Returns Promise<undefined | IClientInfo>

    IClientInfo object if the user is known, otherwise it will return undefined

    -
-
- -
-
- -
-
- -
    - -
  • -

    Set the host for the runtime

    -
    -
    -

    Parameters

    -
      -
    • -
      host: ILiveShareHost
      -

      ILiveShareHost to change

      -
    • -
    • -
      decorate: boolean = true
      -

      choose whether or not to automatically decorate host with BackwardsCompatibilityHostDecorator and LiveShareHostDecorator

      -
    -

    Returns void

-
- -
-
- -
-
- -
    - -
  • -

    Verifies that a client has one of the specified roles.

    -
    -
    -

    Parameters

    -
      -
    • -
      clientId: string
      -

      Client ID to inspect.

      -
    • -
    • -
      allowedRoles: UserMeetingRole[]
      -

      User roles that are allowed.

      -
    -

    Returns Promise<boolean>

    True if the client has one of the specified roles.

    -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share.LiveState.html b/docs/classes/_microsoft_live_share.LiveState.html deleted file mode 100644 index 45e5664c6..000000000 --- a/docs/classes/_microsoft_live_share.LiveState.html +++ /dev/null @@ -1,461 +0,0 @@ -LiveState | Microsoft Live Share SDK
-
- -
-
-
- -
-

Live fluid object that synchronizes a named state and optional data value across clients.

- -

Remarks

The primary benefit of using the LiveState object in a Teams meeting, versus something -like a SharedMap, is that you can restrict the roles of who's allowed to perform state -changes.

-
-
-

Type Parameters

-
    -
  • -

    TState = any

    -

    Optional data object that's synchronized with the state.

    -
-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Properties

-
- -
TypeName: "@microsoft/live-share:LiveState" = ...
-

The objects fluid type/name.

-
-
- -
factory: DataObjectFactory<LiveState<any>, DataObjectTypes> = ...
-

The objects fluid type factory.

-
-
-

Accessors

-
- -
-
- -
-
- -
-
-

Methods

-
- -
-
- -
-
- -
    - -
  • -

    Initialize the object to begin sending/receiving state updates through this DDS.

    - -

    Throws

    error when .initialize() has already been called for this class instance.

    - -

    Throws

    fatal error when .initialize() has already been called for an object of same id but with a different class instance. -This is most common when using dynamic objects through Fluid.

    -
    -
    -

    Parameters

    -
      -
    • -
      initialState: TState
      -

      Initial state value

      -
    • -
    • -
      Optional allowedRoles: UserMeetingRole[]
      -

      Optional. List of roles allowed to make state changes.

      -
    -

    Returns Promise<void>

    a void promise that resolves once complete

    -
-
- -
    - -
  • -

    Set a new state value

    - -

    Throws

    error if initialization has not yet succeeded.

    - -

    Throws

    error if the local user does not have the required roles defined through the allowedRoles prop in .initialize().

    -
    -
    -

    Parameters

    -
      -
    • -
      state: TState
      -

      New state value.

      -
    -

    Returns Promise<void>

    a void promise that resolves once the set event has been sent to the server.

    -
-
- -
-
- -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share.LiveTelemetryLogger.html b/docs/classes/_microsoft_live_share.LiveTelemetryLogger.html deleted file mode 100644 index 422db16a7..000000000 --- a/docs/classes/_microsoft_live_share.LiveTelemetryLogger.html +++ /dev/null @@ -1,355 +0,0 @@ -LiveTelemetryLogger | Microsoft Live Share SDK
-
- -
-
-
- -
-

Wraps the configured logger for the runtime and ensures that certain mandatory properties -are included on outgoing telemetry events.

-
-
-

Hierarchy

-
    -
  • LiveTelemetryLogger
-
-
-
- -
-
-

Constructors

-
- -
-
-

Methods

-
- -
    - -
  • -

    Sends an error event.

    -
    -
    -

    Parameters

    -
      -
    • -
      eventName: string
      -

      Name of the event to send.

      -
    • -
    • -
      Optional error: any
      -

      Optional. Error object to send with event.

      -
    • -
    • -
      Optional additionalProperties: Partial<ILiveTelemetryProperties>
      -

      Optional. Additional properties to include with event.

      -
    -

    Returns void

-
- -
    - -
  • -

    Sends a performance telemetry event.

    -
    -
    -

    Parameters

    -
      -
    • -
      eventName: string
      -

      Name of the event to send.

      -
    • -
    • -
      duration: number
      -

      The duration of the event in milliseconds.

      -
    • -
    • -
      Optional error: any
      -

      Optional. Error object to send with event.

      -
    • -
    • -
      Optional additionalProperties: Partial<ILiveTelemetryProperties>
      -

      Optional. Additional properties to include with event.

      -
    -

    Returns void

-
- -
    - -
  • -

    Sends a generic telemetry event.

    -
    -
    -

    Parameters

    -
      -
    • -
      eventName: string
      -

      Name of the event to send.

      -
    • -
    • -
      Optional error: any
      -

      Optional. Error object to send with event.

      -
    • -
    • -
      Optional additionalProperties: Partial<ILiveTelemetryProperties>
      -

      Optional. Additional properties to include with event.

      -
    -

    Returns void

-
- -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share.LiveTimer.html b/docs/classes/_microsoft_live_share.LiveTimer.html deleted file mode 100644 index c7930d7cb..000000000 --- a/docs/classes/_microsoft_live_share.LiveTimer.html +++ /dev/null @@ -1,497 +0,0 @@ -LiveTimer | Microsoft Live Share SDK
-
- -
-
-
- -
-

Extends Fluid's DataObject class. Intended for use with Live Share custom DDS's that rely on a ILiveShareHost.

-
-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Properties

-
- -
TypeName: "@microsoft/live-share:LiveTimer" = ...
-

The objects fluid type/name.

-
-
- -
factory: DataObjectFactory<LiveTimer, {
    Events: ILiveTimerEvents;
}> = ...
-

The objects fluid type factory.

-
-
-

Accessors

-
- -
-
- -
-
- -
    -
  • get tickRate(): number
  • -
  • -

    Tick rate for timer in milliseconds. The default tick rate is 20 milliseconds

    - -

    Remarks

    Tick rate is used to evaluate how often onTick callback is called. -A high tick rate can also result in the started, played, paused, and finished -callbacks being called slightly later.

    -

    If the tick rate is the default tick rate or lower, timer will tick -at the framerate of the browser.

    -
    -

    Returns number

  • -
  • set tickRate(value): void
  • -
  • -
    -

    Parameters

    -
      -
    • -
      value: number
    -

    Returns void

-
-

Methods

-
- -
-
- -
-
- -
    - -
  • -

    Initialize the object to begin sending/receiving timer updates through this DDS.

    - -

    Throws

    error when .initialize() has already been called for this class instance.

    - -

    Throws

    fatal error when .initialize() has already been called for an object of same id but with a different class instance. -This is most common when using dynamic objects through Fluid.

    -
    -
    -

    Parameters

    -
      -
    • -
      Optional allowedRoles: UserMeetingRole[]
      -

      Optional. List of roles allowed to make state changes.

      -
    -

    Returns Promise<void>

    a void promise that resolves once complete.

    -
-
- -
    - -
  • -

    Pauses the timer.

    - -

    Remarks

    Pausing an already paused timer does nothing.

    - -

    Throws

    error if initialization has not yet succeeded.

    - -

    Throws

    error if the local user does not have the required roles defined through the allowedRoles prop in .initialize().

    -
    -

    Returns Promise<void>

    a void promise that resolves once the pause event has been sent to the server

    -
-
- -
    - -
  • -

    Resumes the timer.

    - -

    Remarks

    Playing an already playing timer does nothing.

    - -

    Throws

    error if initialization has not yet succeeded.

    - -

    Throws

    error if the local user does not have the required roles defined through the allowedRoles prop in .initialize().

    -
    -

    Returns Promise<void>

    a void promise that resolves once the play event has been sent to the server

    -
-
- -
    - -
  • -

    Starts the timer with a specified duration.

    - -

    Remarks

    Starting an already started timer will restart the timer with a new duration.

    - -

    Throws

    error if initialization has not yet succeeded.

    - -

    Throws

    error if the local user does not have the required roles defined through the allowedRoles prop in .initialize().

    -
    -
    -

    Parameters

    -
      -
    • -
      duration: number
      -

      in Milliseconds

      -
    -

    Returns Promise<void>

    a void promise that resolves once the start event has been sent to the server

    -
-
- -
-
- -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share.LocalTimestampProvider.html b/docs/classes/_microsoft_live_share.LocalTimestampProvider.html deleted file mode 100644 index 960bdc4ae..000000000 --- a/docs/classes/_microsoft_live_share.LocalTimestampProvider.html +++ /dev/null @@ -1,274 +0,0 @@ -LocalTimestampProvider | Microsoft Live Share SDK
-
- -
-
-
- -
-

Implements a local timestamp provider for testing purposes.

- -

Remarks

This implementation does not derive from TimestampProvider class as it doesn't need to be started.

-
-
-

Hierarchy

-
    -
  • LocalTimestampProvider
-
-

Implements

-
    -
  • ITimestampProvider
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share.TestLiveShareHost.html b/docs/classes/_microsoft_live_share.TestLiveShareHost.html deleted file mode 100644 index 3f33574b0..000000000 --- a/docs/classes/_microsoft_live_share.TestLiveShareHost.html +++ /dev/null @@ -1,468 +0,0 @@ -TestLiveShareHost | Microsoft Live Share SDK
-
- -
-
-
- -
-

Live Share Host implementation used for local testing.

-
-
-

Hierarchy

-
    -
  • TestLiveShareHost
-
-

Implements

-
-
-
-
- -
-
-

Properties

-
- -
defaultLocalRoles: UserMeetingRole[] = ...
-
- -
defaultRemoteRoles: UserMeetingRole[] = ...
-
- -
LOCAL_MODE_TEST_TOKEN: "test-token" = ...
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Returns the Fluid access token to use for the current session.

    -
    -
    -

    Parameters

    -
      -
    • -
      Optional containerId: string
      -

      Optional. ID of the container being joined. This will be undefined when creating a new container.

      -
    -

    Returns Promise<string>

-
- -
-
- -
    - -
  • -

    Registers the local clients Fluid client ID with the hosts role verification service.

    - -

    Remarks

    Hosts should expect this to be called anytime the Fluid clients underlying socket connects -or reconnects.

    -
    -
    -

    Parameters

    -
      -
    • -
      clientId: string
      -

      Unique ID assigned to the local Fluid client.

      -
    -

    Returns Promise<UserMeetingRole[]>

    An array of meeting roles assigned to the local user.

    -
-
- -
    - -
  • -

    Attempts to save the ID of the Fluid container created to the hosts mapping service.

    - -

    Remarks

    Hosts should return a containerState of "Added" if the mapping was successfully saved, -otherwise a state of "Conflict" should be returned to indicate that another client has -already saved a container ID for the current session.

    -
    -
    -

    Parameters

    -
      -
    • -
      containerId: string
      -

      Id of the Fluid container that was created.

      -
    -

    Returns Promise<IFluidContainerInfo>

    Information indicating the success of mapping assignment.

    -
-
- -
    - -
  • -

    Creates an new live share host for local testing.

    -
    -
    -

    Parameters

    -
      -
    • -
      Optional getLocalTestContainerId: (() => undefined | string)
      -

      Optional. Function to customize reading the test container ID. The default implementation reads the ID from the browsers # URL.

      -
      -
        -
      • -
          -
        • (): undefined | string
        • -
        • -

          Returns undefined | string

    • -
    • -
      Optional setLocalTestContainerId: ((containerId) => void)
      -

      Optional. Function to customize saving the test container ID. The default implementation appends the ID to the browsers # URL.

      -
      -
        -
      • -
          -
        • (containerId): void
        • -
        • -
          -

          Parameters

          -
            -
          • -
            containerId: string
          -

          Returns void

    -

    Returns ILiveShareHost

-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share.TimestampProvider.html b/docs/classes/_microsoft_live_share.TimestampProvider.html deleted file mode 100644 index a75886f9e..000000000 --- a/docs/classes/_microsoft_live_share.TimestampProvider.html +++ /dev/null @@ -1,325 +0,0 @@ -TimestampProvider | Microsoft Live Share SDK
-
- -
-
-
-
- -

Class TimestampProviderAbstract

-
-

Default ITimestampProvider implementation.

-
-
-

Hierarchy

-
-
-

Implements

-
    -
  • ITimestampProvider
-
-
-
- -
-
-

Constructors

-
-
-

Accessors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Accessors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share_canvas.DryCanvas.html b/docs/classes/_microsoft_live_share_canvas.DryCanvas.html deleted file mode 100644 index dbf20cc26..000000000 --- a/docs/classes/_microsoft_live_share_canvas.DryCanvas.html +++ /dev/null @@ -1,964 +0,0 @@ -DryCanvas | Microsoft Live Share SDK
-
- -
-
-
- -
-

Represents a canvas suitable for "dry ink", i.e. the persistent drawing. DryCanvas renders -synchonously.

-
-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
- -
    - -
  • -

    Creates a new InkingCanvas instance, attached to the provided HTMLElement.

    -
    -
    -

    Parameters

    -
      -
    • -
      Optional _parentElement: HTMLElement
      -

      The HTML element this canvas is attached to. InkingCanvas -dynamically creates an HTML5 Canvas element and adds it as a child to parentElement.

      -
    -

    Returns DryCanvas

-
-

Properties

-
- -
referencePoint: CanvasReferencePoint = "center"
-

The canvas' reference point.

-
-
- -
fadeOutDuration: number = 300
-

Configures the time it takes, in milliseconds, for an InkingCanvas to fade out.

-
-
- -
highlighterOpacity: number = 0.5
-

Configures the opacity of highlighter strokes.

-
-
- -
laserShadowOpacity: number = 0.5
-

Configures the opacity of the laser stroke shadow.

-
-
-

Accessors

-
- -
-
- -
-
- -
    -
  • get context(): CanvasRenderingContext2D
  • -
  • -

    Provides access to the underlying HTML5 canvas' CanvsRenderingContext2D

    -
    -

    Returns CanvasRenderingContext2D

-
- -
-
- -
-
- -
-
-

Methods

-
- -
-
- -
-
- -
    - -
  • -

    A "dry" canvas renders multiple strokes which might each have a different brush. -The underlying context's global alpha must be set before rendering each stroke.

    -
    -
    -

    Parameters

    -
      -
    • -
      context: CanvasRenderingContext2D
      -

      The context to set the blend mode on, given the current brush.

      -
    -

    Returns void

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Renders a rectangle onto the canvas.

    -
    -
    -

    Parameters

    -
      -
    • -
      context: CanvasRenderingContext2D
      -

      The target canvas context.

      -
    • -
    • -
      center: IPoint
      -

      The center of the rectangle, in pixels.

      -
    • -
    • -
      halfWidth: number
      -

      The half-width of the rectangle, in pixels.

      -
    • -
    • -
      halfHeight: number
      -

      The half-height of the rectangle, in pixels.

      -
    -

    Returns void

-
- -
-
- -
    - -
  • -

    Determines if this canvas should render asynchronously. When rendering -asynchronously, render operations are scheduled on the next animation frame. -When rendering synchronously, render operations are executed right away.

    -
    -

    Returns boolean

    true if the canvas should render asynchronously, false otherwise.

    -
-
- -
    - -
  • -

    Determines if this canvas renders strokes progressively. When rendering -progressively, the current stroke is rendered incrementally as new points -become available. When progressive rendering is disabled, the current -stroke is fully re-rendered every time.

    -
    -

    Returns boolean

    true if this canvas should render progressively, false otherwise.

    -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share_canvas.DryWetCanvas.html b/docs/classes/_microsoft_live_share_canvas.DryWetCanvas.html deleted file mode 100644 index 26b7223a1..000000000 --- a/docs/classes/_microsoft_live_share_canvas.DryWetCanvas.html +++ /dev/null @@ -1,965 +0,0 @@ -DryWetCanvas | Microsoft Live Share SDK
-
- -
-
-
- -
-

Represents the base class from wet and dry canvases, implementing the common rendering logic.

-
-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Properties

-
- -
referencePoint: CanvasReferencePoint = "center"
-

The canvas' reference point.

-
-
- -
fadeOutDuration: number = 300
-

Configures the time it takes, in milliseconds, for an InkingCanvas to fade out.

-
-
- -
highlighterOpacity: number = 0.5
-

Configures the opacity of highlighter strokes.

-
-
- -
laserShadowOpacity: number = 0.5
-

Configures the opacity of the laser stroke shadow.

-
-
-

Accessors

-
- -
-
- -
-
- -
    -
  • get context(): CanvasRenderingContext2D
  • -
  • -

    Provides access to the underlying HTML5 canvas' CanvsRenderingContext2D

    -
    -

    Returns CanvasRenderingContext2D

-
- -
-
- -
-
- -
-
-

Methods

-
- -
-
- -
-
- -
    - -
  • -

    Sets the appropriate blend mode on the specified context, according -to the current brush. In its base implementation, setBlendMode resets -both the opacity and composite operation to their defaults.

    -
    -
    -

    Parameters

    -
      -
    • -
      context: CanvasRenderingContext2D
      -

      The context to set the blend mode on, given the current brush.

      -
    -

    Returns void

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Renders a rectangle onto the canvas.

    -
    -
    -

    Parameters

    -
      -
    • -
      context: CanvasRenderingContext2D
      -

      The target canvas context.

      -
    • -
    • -
      center: IPoint
      -

      The center of the rectangle, in pixels.

      -
    • -
    • -
      halfWidth: number
      -

      The half-width of the rectangle, in pixels.

      -
    • -
    • -
      halfHeight: number
      -

      The half-height of the rectangle, in pixels.

      -
    -

    Returns void

-
- -
-
- -
    - -
  • -

    Determines if this canvas should render asynchronously. When rendering -asynchronously, render operations are scheduled on the next animation frame. -When rendering synchronously, render operations are executed right away.

    -
    -

    Returns boolean

    true if the canvas should render asynchronously, false otherwise.

    -
-
- -
    - -
  • -

    Determines if this canvas renders strokes progressively. When rendering -progressively, the current stroke is rendered incrementally as new points -become available. When progressive rendering is disabled, the current -stroke is fully re-rendered every time.

    -
    -

    Returns boolean

    true if this canvas should render progressively, false otherwise.

    -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share_canvas.InkingCanvas.html b/docs/classes/_microsoft_live_share_canvas.InkingCanvas.html deleted file mode 100644 index 940bef25d..000000000 --- a/docs/classes/_microsoft_live_share_canvas.InkingCanvas.html +++ /dev/null @@ -1,863 +0,0 @@ -InkingCanvas | Microsoft Live Share SDK
-
- -
-
-
- -
-

Represents the base class for all canvases. InkingCanvas provides resizing, coordinate -tramnslation and base drawingprimitives.

-
-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
- -
    - -
  • -

    Creates a new InkingCanvas instance, attached to the provided HTMLElement.

    -
    -
    -

    Parameters

    -
      -
    • -
      Optional _parentElement: HTMLElement
      -

      The HTML element this canvas is attached to. InkingCanvas -dynamically creates an HTML5 Canvas element and adds it as a child to parentElement.

      -
    -

    Returns InkingCanvas

-
-

Properties

-
- -
referencePoint: CanvasReferencePoint = "center"
-

The canvas' reference point.

-
-
- -
fadeOutDuration: number = 300
-

Configures the time it takes, in milliseconds, for an InkingCanvas to fade out.

-
-
- -
highlighterOpacity: number = 0.5
-

Configures the opacity of highlighter strokes.

-
-
- -
laserShadowOpacity: number = 0.5
-

Configures the opacity of the laser stroke shadow.

-
-
-

Accessors

-
- -
-
- -
-
- -
-
- -
-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Renders a circle onto the canvas.

    -
    -
    -

    Parameters

    -
      -
    • -
      context: CanvasRenderingContext2D
      -

      The target canvas context.

      -
    • -
    • -
      center: IPointerPoint
      -

      The center of the circle, in pixels.

      -
    • -
    • -
      radius: number
      -

      The radius of the circle, in pixels.

      -
    -

    Returns void

-
- -
    - -
  • -

    Renders a "quad", i.e. a shape with four sides, onto the canvas.

    -
    -
    -

    Parameters

    -
      -
    • -
      context: CanvasRenderingContext2D
      -

      The target canvas context.

      -
    • -
    • -
      quad: IQuad
      -

      The quad to render.

      -
    -

    Returns void

-
- -
    - -
  • -

    Renders a rectangle onto the canvas.

    -
    -
    -

    Parameters

    -
      -
    • -
      context: CanvasRenderingContext2D
      -

      The target canvas context.

      -
    • -
    • -
      center: IPoint
      -

      The center of the rectangle, in pixels.

      -
    • -
    • -
      halfWidth: number
      -

      The half-width of the rectangle, in pixels.

      -
    • -
    • -
      halfHeight: number
      -

      The half-height of the rectangle, in pixels.

      -
    -

    Returns void

-
- -
-
- -
    - -
  • -

    Determines if this canvas should render asynchronously. When rendering -asynchronously, render operations are scheduled on the next animation frame. -When rendering synchronously, render operations are executed right away.

    -
    -

    Returns boolean

    true if the canvas should render asynchronously, false otherwise.

    -
-
- -
    - -
  • -

    Resizes this canvas.

    -
    -
    -

    Parameters

    -
      -
    • -
      width: number
      -

      The new width of the canvas, in pixels.

      -
    • -
    • -
      height: number
      -

      The new height of the canvas, in pixels.

      -
    -

    Returns void

-
- -
-
- -
-
- -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share_canvas.InkingManager.html b/docs/classes/_microsoft_live_share_canvas.InkingManager.html deleted file mode 100644 index ad899f568..000000000 --- a/docs/classes/_microsoft_live_share_canvas.InkingManager.html +++ /dev/null @@ -1,906 +0,0 @@ -InkingManager | Microsoft Live Share SDK
-
- -
-
-
- -
-

Handles user interaction with a canvas, and manages the rendering of wet and dry strokes.

-
-
-

Hierarchy

-
    -
  • EventEmitter -
      -
    • InkingManager
-
-
-
- -
-
-

Constructors

-
- -
    - -
  • -

    Creates a new InkingManager instance.

    -
    -
    -

    Parameters

    -
      -
    • -
      hostElement: HTMLElement
      -

      The HTML element to host the canvases and other DOM elements handled by -the InkingManager instance. hostElement shouldn't have any children. The -InkingManager instance might change its attributes, including its style.

      -
    -

    Returns InkingManager

-
-

Properties

-
- -
eraserSize: number = 20
-

The size of the eraser.

-
-
- -
enableStrokeModifierHotKeys: boolean = true
-

Configures whether the Ctrl, Shift and Alt keys can be used to alter the way strokes -are drawn using various tools.

-
-
- -
ephemeralCanvasRemovalDelay: number = 1500
-

Configures the amount of time an ephemeral canvas (i.e. a canvas that renders ephemeral -strokes) remains ready for new strokes before being faded out and removed.

-
-
- -
localClientId: string = ...
-

The default client Id of the device running the application.

-
-
-

Accessors

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-

Methods

-
- -
-
- -
    - -
  • -

    Adds a stroke to the drawing.

    -
    -
    -

    Parameters

    -
      -
    • -
      stroke: IStroke
      -

      The stroke to add. If a stroke with the same id already exists -in the drawing, is it replaced.

      -
    • -
    • -
      Optional options: IAddRemoveStrokeOptions
      -

      Options allowing the caller to force a re-render and/or block the -emission of StrokesAddedEvent.

      -
    -

    Returns void

-
- -
    - -
  • -

    Temporarily blocks the emission of StrokesAddedEvent and StrokesRemovedEvents in order -to batch updates (via addStroke and removeStroke) into the change log. Once the -updates are done, endUpdate must be called.

    -
    -

    Returns void

-
- -
    - -
  • -

    Starts a new wet stroke which will be drawn progressively on the canvas. Multiple wet strokes -can be created at the same time and will not interfere with each other.

    -
    -
    -

    Parameters

    -
      -
    • -
      strokeType: StrokeType
      -

      The type of the stroke to start.

      -
    • -
    • -
      strokeKind: StrokeMode
      -

      The kind of stroke to start.

      -
    • -
    • -
      startPoint: IPointerPoint
      -

      The starting point of the stroke.

      -
    • -
    • -
      Optional options: IStrokeCreationOptions
      -

      Creation options, such as id, points, brush...

      -
    -

    Returns IWetStroke

    An IWetStroke object representing the ongoing stroke.

    -
-
- -
-
- -
-
- -
    - -
  • -

    Unblocks the emission of update events and flushes the change log, leading to a single -StrokesAddedEvent and/or a single StrokesRemovedEvent.

    -
    -

    Returns void

-
- -
    - -
  • -

    Entirely removes any strokes that intersect with the eraser rectangle.

    -
    -
    -

    Parameters

    -
      -
    • -
      p: IPoint
      -

      The center of the eraser rectangle. The size of the rectangle is -determined by the eraserSize property.

      -
    -

    Returns void

-
- -
-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Erases portions of strokes that intersect with the eraser rectangle.

    -
    -
    -

    Parameters

    -
      -
    • -
      p: IPoint
      -

      The center of the eraser rectangle. The size of the rectangle is -determined by the eraserSize property.

      -
    -

    Returns void

-
- -
    - -
  • -

    Removes a stroke from the drawing.

    -
    -
    -

    Parameters

    -
      -
    • -
      id: string
      -

      The id of the stroke to remove. If the stroke doesn't exist, nothing -happens.

      -
    • -
    • -
      Optional options: IAddRemoveStrokeOptions
      -

      Options allowing the caller to force a re-render and/or block the -emission of StrokesRemovedEvent.

      -
    -

    Returns void

-
- -
-
- -
    - -
  • -

    Sets the input filters to use with this InkingManager instance. By default, a jitter -reduction filter is used.

    -
    -
    -

    Parameters

    -
      -
    • -
      Optional inputFilters: InputFilter[]
      -

      The input filters to use, in the order provided. If undefined is -passed, the default input filters are used.

      -
    -

    Returns void

-
- -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share_canvas.InputFilter.html b/docs/classes/_microsoft_live_share_canvas.InputFilter.html deleted file mode 100644 index 564b331fe..000000000 --- a/docs/classes/_microsoft_live_share_canvas.InputFilter.html +++ /dev/null @@ -1,284 +0,0 @@ -InputFilter | Microsoft Live Share SDK
-
- -
-
-
- -
-

Defines an input filter. Input filters are used to transform -input points on the fly.

-
-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
    - -
  • -

    Resets this filter. Some filters use information about -previous points to transform the next point. reset will -be called automatically by InkingManager when a new wet -stroke begins.

    -
    -
    -

    Parameters

    -
    -

    Returns void

-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share_canvas.InputFilterCollection.html b/docs/classes/_microsoft_live_share_canvas.InputFilterCollection.html deleted file mode 100644 index e24a5a3ec..000000000 --- a/docs/classes/_microsoft_live_share_canvas.InputFilterCollection.html +++ /dev/null @@ -1,312 +0,0 @@ -InputFilterCollection | Microsoft Live Share SDK
-
- -
-
-
- -
-

Represents a collection of input filters.

-
-
-

Hierarchy

-
    -
  • InputFilterCollection
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
    - -
  • -

    Resets all the filters in the collection. Some filters -use information about previous points to transform the -next point. reset will be called automatically by -InkingManager when a new wet stroke begins.

    -
    -
    -

    Parameters

    -
    -

    Returns void

-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share_canvas.InputProvider.html b/docs/classes/_microsoft_live_share_canvas.InputProvider.html deleted file mode 100644 index 18734cc9c..000000000 --- a/docs/classes/_microsoft_live_share_canvas.InputProvider.html +++ /dev/null @@ -1,367 +0,0 @@ -InputProvider | Microsoft Live Share SDK
-
- -
-
-
- -
-

A basic input event provider implementation.

-
-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Properties

-
- -
pointerDownEvent: MulticastEvent<IPointerEvent> = ...
-
- -
pointerEnterEvent: MulticastEvent<IPointerEvent> = ...
-
- -
pointerLeaveEvent: MulticastEvent<IPointerEvent> = ...
-
- -
pointerMoveEvent: MulticastEvent<IPointerMoveEvent> = ...
-
- -
pointerUpEvent: MulticastEvent<IPointerEvent> = ...
-
-

Accessors

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share_canvas.JitterFilter.html b/docs/classes/_microsoft_live_share_canvas.JitterFilter.html deleted file mode 100644 index d453fdb8b..000000000 --- a/docs/classes/_microsoft_live_share_canvas.JitterFilter.html +++ /dev/null @@ -1,286 +0,0 @@ -JitterFilter | Microsoft Live Share SDK
-
- -
-
-
- -
-

Implements a jitter reduction filter, which straightens stroke by ignoring -micro movements detected by the input device, mainly pens.

-
-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
    - -
  • -

    Resets this filter. Some filters use information about -previous points to transform the next point. reset will -be called automatically by InkingManager when a new wet -stroke begins.

    -
    -
    -

    Parameters

    -
    -

    Returns void

-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share_canvas.LaserPointerCanvas.html b/docs/classes/_microsoft_live_share_canvas.LaserPointerCanvas.html deleted file mode 100644 index 1a38f2b3b..000000000 --- a/docs/classes/_microsoft_live_share_canvas.LaserPointerCanvas.html +++ /dev/null @@ -1,964 +0,0 @@ -LaserPointerCanvas | Microsoft Live Share SDK
-
- -
-
-
- -
-

Represents a canvas that implements the laser pointer behavior.

-
-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Properties

-
- -
referencePoint: CanvasReferencePoint = "center"
-

The canvas' reference point.

-
-
- -
fadeOutDuration: number = 300
-

Configures the time it takes, in milliseconds, for an InkingCanvas to fade out.

-
-
- -
highlighterOpacity: number = 0.5
-

Configures the opacity of highlighter strokes.

-
-
- -
laserShadowOpacity: number = 0.5
-

Configures the opacity of the laser stroke shadow.

-
-
-

Accessors

-
- -
-
- -
-
- -
    -
  • get context(): CanvasRenderingContext2D
  • -
  • -

    Provides access to the underlying HTML5 canvas' CanvsRenderingContext2D

    -
    -

    Returns CanvasRenderingContext2D

-
- -
-
- -
-
- -
-
-

Methods

-
- -
-
- -
-
- -
    - -
  • -

    A "wet" canvas always renders a single stroke and is discarded when that stroke ends. -It needs to be properly composited on whatever other DOM element it is overlayed on, -which means the HTML5 canvas itself must have its opacity set up appropriately.

    -
    -
    -

    Parameters

    -
      -
    • -
      context: CanvasRenderingContext2D
      -

      The context to set the blend mode on, given the current brush.

      -
    -

    Returns void

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Renders a "quad", i.e. a shape with four sides, onto the canvas.

    -
    -
    -

    Parameters

    -
      -
    • -
      context: CanvasRenderingContext2D
      -

      The target canvas context.

      -
    • -
    • -
      quad: IQuad
      -

      The quad to render.

      -
    -

    Returns void

-
- -
    - -
  • -

    Renders a rectangle onto the canvas.

    -
    -
    -

    Parameters

    -
      -
    • -
      context: CanvasRenderingContext2D
      -

      The target canvas context.

      -
    • -
    • -
      center: IPoint
      -

      The center of the rectangle, in pixels.

      -
    • -
    • -
      halfWidth: number
      -

      The half-width of the rectangle, in pixels.

      -
    • -
    • -
      halfHeight: number
      -

      The half-height of the rectangle, in pixels.

      -
    -

    Returns void

-
- -
-
- -
    - -
  • -

    Determines if this canvas should render asynchronously. When rendering -asynchronously, render operations are scheduled on the next animation frame. -When rendering synchronously, render operations are executed right away.

    -
    -

    Returns boolean

    true if the canvas should render asynchronously, false otherwise.

    -
-
- -
    - -
  • -

    Determines if this canvas renders strokes progressively. When rendering -progressively, the current stroke is rendered incrementally as new points -become available. When progressive rendering is disabled, the current -stroke is fully re-rendered every time.

    -
    -

    Returns boolean

    true if this canvas should render progressively, false otherwise.

    -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share_canvas.LiveCanvas.html b/docs/classes/_microsoft_live_share_canvas.LiveCanvas.html deleted file mode 100644 index 77b00e369..000000000 --- a/docs/classes/_microsoft_live_share_canvas.LiveCanvas.html +++ /dev/null @@ -1,504 +0,0 @@ -LiveCanvas | Microsoft Live Share SDK
-
- -
-
-
- -
-

Enables live and collaborative inking.

-
-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Properties

-
- -
onCreateLiveCursor?: ((clientId, userInfo?) => LiveCursor)
-
-

Type declaration

-
    -
  • -
      -
    • (clientId, userInfo?): LiveCursor
    • -
    • -

      Optional callback that allows the consuming application to provide its own -live cursor visual representation by extending the abstract LiveCursor -class. The callback is passed the user information retrieved via the -onGetLocalUserInfo calback, if provided.

      -
      -
      -

      Parameters

      -
        -
      • -
        clientId: string
      • -
      • -
        Optional userInfo: IUserInfo
      -

      Returns LiveCursor

-
- -
onGetLocalUserPictureUrl?: (() => undefined | string)
-
-

Type declaration

-
    -
  • -
      -
    • (): undefined | string
    • -
    • -

      Optional callback that allows the consuming application to provide a -a profile picture that will be used on remote devices to render shared cursors.

      -
      -

      Returns undefined | string

-
- -
TypeName: "@microsoft/shared-inking-session" = ...
-

The object's Fluid type/name.

-
-
- -
factory: DataObjectFactory<LiveCanvas, DataObjectTypes> = ...
-

The object's Fluid type factory.

-
-
-

Accessors

-
- -
-
- -
    -
  • get initializeState(): LiveDataObjectInitializeState
  • -
  • -

    The initialization status of the data object.

    - -

    Remarks

    Used to know whether it is safe to call .initialize()

    -
    -

    Returns LiveDataObjectInitializeState

  • -
  • set initializeState(value): void
  • -
  • -
    -

    Parameters

    -
    -

    Returns void

-
- -
-
- -
    -
  • get isInitialized(): boolean
  • -
  • -

    Flag that indicates whether initialization has succeeded or not.

    - -

    Remarks

    This field is true when initializeState is succeeded, or false when initializeState is any other value.

    -
    -

    Returns boolean

-
-

Methods

-
- -
    - -
  • -

    Get the client info for a given clientId

    -
    -
    -

    Parameters

    -
      -
    • -
      clientId: string
      -

      Fluid clientId we are requesting user info for

      -
    -

    Returns Promise<undefined | IClientInfo>

    IClientInfo object if the user is known, otherwise it will return undefined

    -
-
- -
-
- -
    - -
  • -

    Initializes the live inking session.

    -
    -
    -

    Parameters

    -
      -
    • -
      inkingManager: InkingManager
      -

      The InkingManager instance providing the drawing and events that will be synchronized across clients.

      -
    • -
    • -
      Optional allowedRoles: UserMeetingRole[]
    -

    Returns Promise<void>

    a void promise that resolves once complete.

    -
-
- -
-
- -
    - -
  • -

    Verify that the user has the required roles

    -
    -

    Returns Promise<boolean>

    boolean true if user has the required roles

    -
-
- -
    - -
  • -

    Waits until connected and gets the most recent clientId

    -
    -

    Returns Promise<string>

    clientId

    -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share_canvas.LiveCursor.html b/docs/classes/_microsoft_live_share_canvas.LiveCursor.html deleted file mode 100644 index 9890d8a69..000000000 --- a/docs/classes/_microsoft_live_share_canvas.LiveCursor.html +++ /dev/null @@ -1,334 +0,0 @@ -LiveCursor | Microsoft Live Share SDK
-
- -
-
-
- -
-

Represents a live (shared) cursor. Applications that want to customize -the appearance of cursors on the screen should extend LiveCursor and -override its renderedElement property to return a custom HTML element.

-
-
-

Hierarchy

-
    -
  • LiveCursor
-
-
-
- -
-
-

Constructors

-
-
-

Properties

-
-
-

Accessors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Properties

-
- -
clientId: string
-
-

Accessors

-
- -
-
- -
    -
  • get renderedElement(): HTMLElement
  • -
  • -

    Returns an HTML element representing the cursor. Applications -that extend LiveCursor must override get renderedElement -to return a custom built HTML element.

    -
    -

    Returns HTMLElement

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share_canvas.MulticastEvent.html b/docs/classes/_microsoft_live_share_canvas.MulticastEvent.html deleted file mode 100644 index ec773afb1..000000000 --- a/docs/classes/_microsoft_live_share_canvas.MulticastEvent.html +++ /dev/null @@ -1,294 +0,0 @@ -MulticastEvent | Microsoft Live Share SDK
-
- -
-
-
- -
-

Implements a simple typed multicast event.

-
-
-

Type Parameters

-
    -
  • -

    TArgs

-
-

Hierarchy

-
    -
  • MulticastEvent
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
emit -off -on -
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share_canvas.PointerInputProvider.html b/docs/classes/_microsoft_live_share_canvas.PointerInputProvider.html deleted file mode 100644 index 03967b92b..000000000 --- a/docs/classes/_microsoft_live_share_canvas.PointerInputProvider.html +++ /dev/null @@ -1,394 +0,0 @@ -PointerInputProvider | Microsoft Live Share SDK
-
- -
-
-
- -
-

InputProvider implementation that hooks into a DOM element's pointer events.

-
-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Properties

-
- -
element: HTMLElement
-
- -
pointerDownEvent: MulticastEvent<IPointerEvent> = ...
-
- -
pointerEnterEvent: MulticastEvent<IPointerEvent> = ...
-
- -
pointerLeaveEvent: MulticastEvent<IPointerEvent> = ...
-
- -
pointerMoveEvent: MulticastEvent<IPointerMoveEvent> = ...
-
- -
pointerUpEvent: MulticastEvent<IPointerEvent> = ...
-
-

Accessors

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share_canvas.Stroke.html b/docs/classes/_microsoft_live_share_canvas.Stroke.html deleted file mode 100644 index a07a9008d..000000000 --- a/docs/classes/_microsoft_live_share_canvas.Stroke.html +++ /dev/null @@ -1,549 +0,0 @@ -Stroke | Microsoft Live Share SDK
-
- -
-
-
- -
-

Represents a concrete stroke object.

-
-
-

Hierarchy

-
    -
  • Stroke
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Accessors

-
- -
-
- -
-
- -
-
- -
-
- -
-
-

Methods

-
- -
    - -
  • -

    Returns {
        next: (() => {
            done: boolean;
            value: IPointerPoint;
        });
    }

    -
-
- -
-
- -
    - -
  • -

    Adds the specified points to the stroke. Points are added if they are -sufficiently far from each other.

    -
    -
    -

    Parameters

    -
    -

    Returns boolean

    true if at least one point was added, false otherwise.

    -
-
- -
-
- -
    - -
  • -

    Deserializes the specified stroke string and sets this stroke's brush, -points and other proprties accordingly.

    -
    -
    -

    Parameters

    -
      -
    • -
      serializedStroke: string
      -

      The serialized stroke.

      -
    -

    Returns void

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Splits this stroke into several other ones by "erasing" the portions that -are within the eraser rectangle.

    -
    -
    -

    Parameters

    -
      -
    • -
      eraserRect: IRect
      -

      The eraser rectangle.

      -
    -

    Returns undefined | IStroke[]

    An array of new strokes (which might be empty if the whole stroke -was erased), or undefined if the stroke was unchanged.

    -
-
- -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share_canvas.WetCanvas.html b/docs/classes/_microsoft_live_share_canvas.WetCanvas.html deleted file mode 100644 index 64cb78889..000000000 --- a/docs/classes/_microsoft_live_share_canvas.WetCanvas.html +++ /dev/null @@ -1,967 +0,0 @@ -WetCanvas | Microsoft Live Share SDK
-
- -
-
-
- -
-

Represents a canvas suitable for "wet ink", i.e. an ongoing stroke.

-
-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
- -
    - -
  • -

    Creates a new InkingCanvas instance, attached to the provided HTMLElement.

    -
    -
    -

    Parameters

    -
      -
    • -
      Optional _parentElement: HTMLElement
      -

      The HTML element this canvas is attached to. InkingCanvas -dynamically creates an HTML5 Canvas element and adds it as a child to parentElement.

      -
    -

    Returns WetCanvas

-
-

Properties

-
- -
referencePoint: CanvasReferencePoint = "center"
-

The canvas' reference point.

-
-
- -
fadeOutDuration: number = 300
-

Configures the time it takes, in milliseconds, for an InkingCanvas to fade out.

-
-
- -
highlighterOpacity: number = 0.5
-

Configures the opacity of highlighter strokes.

-
-
- -
laserShadowOpacity: number = 0.5
-

Configures the opacity of the laser stroke shadow.

-
-
-

Accessors

-
- -
-
- -
-
- -
    -
  • get context(): CanvasRenderingContext2D
  • -
  • -

    Provides access to the underlying HTML5 canvas' CanvsRenderingContext2D

    -
    -

    Returns CanvasRenderingContext2D

-
- -
-
- -
-
- -
-
-

Methods

-
- -
-
- -
-
- -
    - -
  • -

    A "wet" canvas always renders a single stroke and is discarded when that stroke ends. -It needs to be properly composited on whatever other DOM element it is overlayed on, -which means the HTML5 canvas itself must have its opacity set up appropriately.

    -
    -
    -

    Parameters

    -
      -
    • -
      context: CanvasRenderingContext2D
      -

      The context to set the blend mode on, given the current brush.

      -
    -

    Returns void

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Renders a rectangle onto the canvas.

    -
    -
    -

    Parameters

    -
      -
    • -
      context: CanvasRenderingContext2D
      -

      The target canvas context.

      -
    • -
    • -
      center: IPoint
      -

      The center of the rectangle, in pixels.

      -
    • -
    • -
      halfWidth: number
      -

      The half-width of the rectangle, in pixels.

      -
    • -
    • -
      halfHeight: number
      -

      The half-height of the rectangle, in pixels.

      -
    -

    Returns void

-
- -
-
- -
    - -
  • -

    Determines if this canvas should render asynchronously. When rendering -asynchronously, render operations are scheduled on the next animation frame. -When rendering synchronously, render operations are executed right away.

    -
    -

    Returns boolean

    true if the canvas should render asynchronously, false otherwise.

    -
-
- -
    - -
  • -

    Determines if this canvas renders strokes progressively. When rendering -progressively, the current stroke is rendered incrementally as new points -become available. When progressive rendering is disabled, the current -stroke is fully re-rendered every time.

    -
    -

    Returns boolean

    true if this canvas should render progressively, false otherwise.

    -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share_media.LiveMediaSession.html b/docs/classes/_microsoft_live_share_media.LiveMediaSession.html deleted file mode 100644 index 94d8e2b11..000000000 --- a/docs/classes/_microsoft_live_share_media.LiveMediaSession.html +++ /dev/null @@ -1,523 +0,0 @@ -LiveMediaSession | Microsoft Live Share SDK
-
- -
-
-
- -
-

Live fluid object that synchronizes media playback across multiple clients.

-
-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Properties

-
- -
TypeName: "@microsoft/fluid-media:SharedMediaSession" = ...
-

The objects fluid type name.

-
-
- -
factory: DataObjectFactory<LiveMediaSession, DataObjectTypes> = ...
-

The objects fluid type factory.

-
-
-

Accessors

-
- -
    -
  • get actionThrottler(): MediaSessionActionThrottler
  • -
  • -

    Extension point that lets applications replace the default logic for throttling the sessions -local sync behavior.

    - -

    Remarks

    The LiveMediaCoordinator is fairly aggressive at wanting to keep the local media player -in sync with the rest of the group. This aggressiveness can result in the coordinator sending -new sync actions before the local player has finished responding to the previous sync action. -The ActionThrottler gives apps fine grain control over how aggressive they want sync to be.

    -

    By default, a RepeatedAction throttler is used which prevents the same sync action from -being sent within an adjustable time period.

    -
    -

    Returns MediaSessionActionThrottler

  • -
  • set actionThrottler(value): void
  • -
  • -
    -

    Parameters

    -
    -

    Returns void

-
- -
-
- -
    -
  • get initializeState(): LiveDataObjectInitializeState
  • -
  • -

    The initialization status of the data object.

    - -

    Remarks

    Used to know whether it is safe to call .initialize()

    -
    -

    Returns LiveDataObjectInitializeState

  • -
  • set initializeState(value): void
  • -
  • -
    -

    Parameters

    -
    -

    Returns void

-
- -
    -
  • get isInitialized(): boolean
  • -
  • -

    Flag that indicates whether initialization has succeeded or not.

    - -

    Remarks

    This field is true when initializeState is succeeded, or false when initializeState is any other value.

    -
    -

    Returns boolean

-
- -
-
-

Methods

-
- -
    - -
  • -

    Get the client info for a given clientId

    -
    -
    -

    Parameters

    -
      -
    • -
      clientId: string
      -

      Fluid clientId we are requesting user info for

      -
    -

    Returns Promise<undefined | IClientInfo>

    IClientInfo object if the user is known, otherwise it will return undefined

    -
-
- -
-
- -
    - -
  • -

    Initialize the object to begin sending/receiving group playback updates through this DDS.

    - -

    Throws

    error when .initialize() has already been called for this class instance.

    -
    -
    -

    Parameters

    -
      -
    • -
      Optional allowedRoles: UserMeetingRole[]
      -

      Optional. List of roles allowed to group transport operations like play/pause/seek/setTrack.

      -
    -

    Returns Promise<void>

    a void promise that resolves once complete.

    -
-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Verify that the user has the required roles

    -
    -

    Returns Promise<boolean>

    boolean true if user has the required roles

    -
-
- -
    - -
  • -

    Waits until connected and gets the most recent clientId

    -
    -

    Returns Promise<string>

    clientId

    -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share_media.LiveMediaSessionCoordinator.html b/docs/classes/_microsoft_live_share_media.LiveMediaSessionCoordinator.html deleted file mode 100644 index ea5170421..000000000 --- a/docs/classes/_microsoft_live_share_media.LiveMediaSessionCoordinator.html +++ /dev/null @@ -1,533 +0,0 @@ -LiveMediaSessionCoordinator | Microsoft Live Share SDK
-
- -
-
-
- -
-

The LiveMediaSessionCoordinator tracks the playback & position state of all other -clients being synchronized with. It is responsible for keeping the local media player -in sync with the group.

-
-
-

Hierarchy

-
    -
  • EventEmitter -
      -
    • LiveMediaSessionCoordinator
-
-
-
- -
-
-

Properties

-
- -
canPlayPause: boolean = true
-

Controls whether or not the local client is allowed to instruct the group to play or pause.

- -

Remarks

This flag largely meant to influence decisions made by the coordinator and can be used by -the UI to determine what controls should be shown to the user. It does not provide any -security in itself.

-

If your app is running in a semi-trusted environment where only some clients are allowed -to play/pause media, you should use "role based verification" to enforce those policies.

-
-
- -
canSeek: boolean = true
-

Controls whether or not the local client is allowed to seek the group to a new playback -position.

- -

Remarks

This flag largely meant to influence decisions made by the coordinator and can be used by -the UI to determine what controls should be shown to the user. It does not provide any -security in itself.

-

If your app is running in a semi-trusted environment where only some clients are allowed -to change the playback position, you should use "role based verification" to enforce those policies.

-
-
- -
canSendPositionUpdates: boolean = true
-

Controls whether or not the local client is allowed to send position updates to the group.

- -

Remarks

This flag largely meant to limit the number of signals sent to the group for performance reasons. -It does not provide any security in itself.

-
-
- -
canSetTrack: boolean = true
-

Controls whether or not the local client is allowed to change tracks.

- -

Remarks

This flag largely meant to influence decisions made by the coordinator and can be used by -the UI to determine what controls should be shown to the user. It does not provide any -security in itself.

-

If your app is running in a semi-trusted environment where only some clients are allowed -to change tracks, you should use "role based verification" to enforce those policies.

-
-
- -
canSetTrackData: boolean = true
-

Controls whether or not the local client is allowed to change the tracks custom data object.

- -

Remarks

This flag largely meant to influence decisions made by the coordinator and can be used by -the UI to determine what controls should be shown to the user. It does not provide any -security in itself.

-

If your app is running in a semi-trusted environment where only some clients are allowed -to change the tracks data object, you should use "role based verification" to enforce those -policies.

-
-
-

Accessors

-
- -
-
- -
-
- -
-
-

Methods

-
- -
    - -
  • -

    Begins a new local suspension.

    - -

    Remarks

    Suspension temporarily suspend the clients local synchronization with the group. This can -be useful for displaying ads to users or temporarily disconnecting from the session while -the user seeks the video using a timeline scrubber.

    -

    Multiple simultaneous suspensions are allowed and when the last suspension ends the local -client will be immediately re-synchronized with the group.

    -

    A "Dynamic Wait Point" can be specified when beginSuspension() is called and the wait -point will be broadcast to all other clients in the group. Those clients will then -automatically enter a suspension state once they reach the positions specified by the -wait point. Clients that are passed the wait point will immediately suspend.

    -

    Any wait point based suspension (dynamic or static) will result in all clients remaining -in a suspension state until the list client ends their suspension. This behavior can be -conditionally bypassed by settings the wait points maxClients value.

    -

    Throws an exception if the session/coordinator hasn't been initialized.

    -
    -
    -

    Parameters

    -
      -
    • -
      Optional waitPoint: CoordinationWaitPoint
      -

      Optional. Dynamic wait point to broadcast to all of the clients.

      -
    -

    Returns MediaSessionCoordinatorSuspension

    The suspension object. Call end() on the returned suspension to end the suspension.

    -
-
- -
-
- -
    - -
  • -

    Instructs the group to pause the current track.

    - -

    Remarks

    Throws an exception if the session/coordinator hasn't been initialized, no track has been -loaded, or canPlayPause is false.

    -
    -

    Returns Promise<void>

    a void promise that resolves once complete, throws if user does not have proper roles

    -
-
- -
    - -
  • -

    Instructs the group to play the current track.

    - -

    Remarks

    Throws an exception if the session/coordinator hasn't been initialized, no track has been -loaded, or canPlayPause is false.

    -
    -

    Returns Promise<void>

    a void promise that resolves once complete, throws if user does not have proper roles

    -
-
- -
    - -
  • -

    Instructs the group to seek to a new position within the current track.

    - -

    Remarks

    Throws an exception if the session/coordinator hasn't been initialized, no track has been -loaded, or canSeek is false.

    -
    -
    -

    Parameters

    -
      -
    • -
      time: number
      -

      Playback position in seconds to seek to.

      -
    -

    Returns Promise<void>

    a void promise that resolves once complete, throws if user does not have proper roles

    -
-
- -
    - -
  • -

    Instructs the group to load a new track.

    - -

    Remarks

    Throws an exception if the session/coordinator hasn't been initialized or canSetTrack is -false.

    -
    -
    -

    Parameters

    -
      -
    • -
      metadata: null | ExtendedMediaMetadata
      -

      The track to load or null to indicate that the end of the track is reached.

      -
    • -
    • -
      Optional waitPoints: CoordinationWaitPoint[]
      -

      Optional. List of static wait points to configure for the track. Dynamic wait points can be added via the beginSuspension() call.

      -
    -

    Returns Promise<void>

    a void promise that resolves once complete, throws if user does not have proper roles

    -
-
- -
    - -
  • -

    Updates the track data object for the current track.

    - -

    Remarks

    The track data object can be used by applications to synchronize things like pitch, roll, -and yaw of a 360 video. This data object will be reset to null anytime the track changes.

    -

    Throws an exception if the session/coordinator hasn't been initialized or canSetTrackData is -false.

    -
    -
    -

    Parameters

    -
      -
    • -
      data: null | object
      -

      New data object to sync with the group. This value will be synchronized using a last writer wins strategy.

      -
    -

    Returns Promise<void>

    a void promise that resolves once complete, throws if user does not have proper roles

    -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share_media.LiveMediaSessionCoordinatorSuspension.html b/docs/classes/_microsoft_live_share_media.LiveMediaSessionCoordinatorSuspension.html deleted file mode 100644 index d148675df..000000000 --- a/docs/classes/_microsoft_live_share_media.LiveMediaSessionCoordinatorSuspension.html +++ /dev/null @@ -1,301 +0,0 @@ -LiveMediaSessionCoordinatorSuspension | Microsoft Live Share SDK
-
- -
-
-
- -
-

Suspension object for when group synchronization is suspended for the local user.

-
-
-

Hierarchy

-
    -
  • LiveMediaSessionCoordinatorSuspension
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
-
-

Accessors

-
-
-

Methods

-
end -
-
-

Constructors

-
- -
-
-

Accessors

-
- -
-
-

Methods

-
- -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share_media.MediaPlayerSynchronizer.html b/docs/classes/_microsoft_live_share_media.MediaPlayerSynchronizer.html deleted file mode 100644 index 89505591e..000000000 --- a/docs/classes/_microsoft_live_share_media.MediaPlayerSynchronizer.html +++ /dev/null @@ -1,556 +0,0 @@ -MediaPlayerSynchronizer | Microsoft Live Share SDK
-
- -
-
-
- -
-

Synchronizes a local HTML Media Element with a group of remote HTML Media Elements.

- -

Remarks

All of an apps transport control commands should be routed through the synchronizer. If the -app is not currently joined to the group media session, the commands will be applied directly -to the local player. When the group session is joined the commands will be broadcast to the -group in addition to being applied to the local player.

-
-
-

Hierarchy

-
    -
  • EventEmitter -
      -
    • MediaPlayerSynchronizer
-
-
-
- -
-
-

Constructors

-
- -
-
-

Accessors

-
- -
-
- -
-
- -
    -
  • get viewOnly(): boolean
  • -
  • -

    If true the client is in a view only mode.

    - -

    Remarks

    Toggling this value to true results in mediaSession.coordinator.canPlayPause, -mediaSession.coordinator.canSeek, mediaSession.coordinator.canSetTrack, and -mediaSession.coordinator.canSetTrackData all being set to false. For more fine -grained control over the local clients policies, call the mediaSession.coordinator -directly.

    -
    -

    Returns boolean

  • -
  • set viewOnly(value): void
  • -
  • -
    -

    Parameters

    -
      -
    • -
      value: boolean
    -

    Returns void

-
- -
-
-

Methods

-
- -
-
- -
    - -
  • -

    Begin a local seek operation.

    - -

    Remarks

    UI can call this when a user grabs a timeline scrubber and starts scrubbing the video to a -new playback position. The synchronizer will being a new suspension which temporarily -disconnects the client for the rest of the group for synchronization purposes. Calling -endSeek() will end the suspension and seek the group to the users final seek position.

    -
    -

    Returns void

-
- -
-
- -
    - -
  • -

    Ends a seek operation that was started by calling beginSeek().

    -
    -
    -

    Parameters

    -
      -
    • -
      seekTo: number
      -

      Playback position in seconds to seek the group to.

      -
    -

    Returns void

-
- -
    - -
  • -

    Tells the group to pause the current video.

    - -

    Remarks

    For proper operation apps should avoid calling mediaSession.coordinator.pause() directly -and instead use the synchronizers pause() method.

    -
    -

    Returns Promise<void>

    a void promise that resolves once complete, throws if user does not have proper roles

    -
-
- -
    - -
  • -

    Tells the group to begin playing the current video.

    - -

    Remarks

    For proper operation apps should avoid calling mediaSession.coordinator.play() directly -and instead use the synchronizers play() method.

    -
    -

    Returns Promise<void>

    a void promise that resolves once complete, throws if user does not have proper roles

    -
-
- -
-
- -
    - -
  • -

    Tells the group to seek the current video to a new playback position.

    - -

    Remarks

    For proper operation apps should avoid calling mediaSession.coordinator.seekTo() directly -and instead use the synchronizers seekTo() method.

    -
    -
    -

    Parameters

    -
      -
    • -
      time: number
    -

    Returns Promise<void>

    a void promise that resolves once complete, throws if user does not have proper roles

    -
-
- -
    - -
  • -

    Tells the group to change to a new track.

    - -

    Remarks

    For proper operation apps should avoid calling mediaSession.coordinator.setTrack() directly -and instead use the synchronizers setTrack() method.

    -
    -
    -

    Parameters

    -
    -

    Returns Promise<void>

    a void promise that resolves once complete, throws if user does not have proper roles

    -
-
- -
    - -
  • -

    Updates the current tracks data object.

    - -

    Remarks

    For proper operation apps should avoid calling mediaSession.coordinator.setTrackData() directly -and instead use the synchronizers setTrackData() method.

    -
    -
    -

    Parameters

    -
      -
    • -
      data: null | object
    -

    Returns Promise<void>

    a void promise that resolves once complete, throws if user does not have proper roles

    -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share_media.MediaSessionActionThrottler.html b/docs/classes/_microsoft_live_share_media.MediaSessionActionThrottler.html deleted file mode 100644 index 69971100f..000000000 --- a/docs/classes/_microsoft_live_share_media.MediaSessionActionThrottler.html +++ /dev/null @@ -1,259 +0,0 @@ -MediaSessionActionThrottler | Microsoft Live Share SDK
-
- -
-
-
-
- -

Class MediaSessionActionThrottlerAbstract

-
-

Base class for action throttlers.

-
-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share_media.RepeatedActionThrottler.html b/docs/classes/_microsoft_live_share_media.RepeatedActionThrottler.html deleted file mode 100644 index a65dc9deb..000000000 --- a/docs/classes/_microsoft_live_share_media.RepeatedActionThrottler.html +++ /dev/null @@ -1,285 +0,0 @@ -RepeatedActionThrottler | Microsoft Live Share SDK
-
- -
-
-
- -
-

A Throttler that passes through all actions but will only let an action be repeated once every 2 seconds.

-
-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
-
-

Accessors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Accessors

-
- -
-
-

Methods

-
- -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share_media.VolumeManager.html b/docs/classes/_microsoft_live_share_media.VolumeManager.html deleted file mode 100644 index c83c476de..000000000 --- a/docs/classes/_microsoft_live_share_media.VolumeManager.html +++ /dev/null @@ -1,394 +0,0 @@ -VolumeManager | Microsoft Live Share SDK
-
- -
-
-
- -
-

Smooth audio level changes when volume is modified, or if volume limiting has started/ended.

-
-
-

Hierarchy

-
    -
  • VolumeManager
-
-
-
- -
-
-

Constructors

-
- -
-
-

Accessors

-
- -
-
- -
    -
  • get limitLevel(): number
  • -
  • -

    Target level to lower volume to.

    - -

    Remarks

    Expressed as a value between 0.0 and 1.0. The value is applied based upon the configured -levelType. The default value is 0.1.

    -

    For a level type of LevelType.fixed the value is the exact level the volume will be -lowered to. The default value of 0.1 would cause the volume to be lowered to 0.1.

    -

    For a level type of LevelType.percentage the value is the percentage by which the volume -level should be lowered to. The default value of 0.1 would cause the volume to be lowered -to 10% of its starting value.

    -
    -

    Returns number

  • -
  • set limitLevel(value): void
  • -
  • -
    -

    Parameters

    -
      -
    • -
      value: number
    -

    Returns void

-
- -
-
- -
    -
  • get volume(): number
  • -
  • -

    The selected volume.

    - -

    Remarks

    Expressed as a value between 0.0 and 1.0. The default value is 1.0. -Can be used for things like volume sliders.

    -

    Does not return the current volume if limiting is enabled, but the desired volume.

    -
    -

    Returns number

  • -
  • set volume(value): void
  • -
  • -
    -

    Parameters

    -
      -
    • -
      value: number
    -

    Returns void

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/_microsoft_live_share_turbo.AzureTurboClient.html b/docs/classes/_microsoft_live_share_turbo.AzureTurboClient.html deleted file mode 100644 index 5c6128046..000000000 --- a/docs/classes/_microsoft_live_share_turbo.AzureTurboClient.html +++ /dev/null @@ -1,430 +0,0 @@ -AzureTurboClient | Microsoft Live Share SDK
-
- -
-
-
- -
-

The FluidTurboClient implementation for the AzureClient.

- -

See

FluidTurboClient

-
-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Accessors

-
- -
    -
  • get canSendBackgroundUpdates(): boolean
  • -
  • -

    Setting for whether LiveDataObject instances using LiveObjectSynchronizer can send background updates. -Default value is true.

    - -

    Remarks

    This is useful for scenarios where there are a large number of participants in a session, since service performance degrades as more socket connections are opened. -Intended for use when a small number of users are intended to be "in control", such as the LiveFollowMode class's startPresenting() feature. -Set to true when the user is eligible to send background updates (e.g., "in control"), or false when that user is not in control. -This setting will not prevent the local user from explicitly changing the state of objects using LiveObjectSynchronizer, such as .set() in LiveState. -Impacts background updates of LiveState, LivePresence, LiveTimer, and LiveFollowMode.

    -
    -

    Returns boolean

  • -
  • set canSendBackgroundUpdates(value): void
  • -
  • -
    -

    Parameters

    -
      -
    • -
      value: boolean
    -

    Returns void

-
- -
    -
  • get results(): undefined | {
        container: IFluidContainer;
        services: AzureContainerServices;
    }
  • -
  • -

    Get the Fluid join container results

    -
    -

    Returns undefined | {
        container: IFluidContainer;
        services: AzureContainerServices;
    }

-
- -
-
-

Methods

-
- -
    - -
  • -

    Creates a new detached container instance in the Azure Fluid Relay.

    -
    -
    -

    Parameters

    -
      -
    • -
      Optional initialObjects: LoadableObjectClassRecord
      -

      Optional. Fluid ContainerSchema initialObjects.

      -
    -

    Returns Promise<{
        container: IFluidContainer;
        services: AzureContainerServices;
    }>

    New detached container instance along with associated services.

    -
-
- -
    - -
  • -

    Accesses the existing container given its unique ID in the Azure Fluid Relay.

    -
    -
    -

    Parameters

    -
      -
    • -
      id: string
      -

      Unique ID of the container in Azure Fluid Relay.

      -
    • -
    • -
      Optional initialObjects: LoadableObjectClassRecord
      -

      Optional. Fluid ContainerSchema initialObjects.

      -
    -

    Returns Promise<{
        container: IFluidContainer;
        services: AzureContainerServices;
    }>

    Existing container instance along with associated services.

    -
-
- -
    - -
  • -

    Get the container schema to use within a FluidTurboClient container.

    -
    -
    -

    Parameters

    -
      -
    • -
      Optional initialObjects: LoadableObjectClassRecord
      -

      Optional. Initial objects to add to the schema

      -
    -

    Returns {
        dynamicObjectTypes: LoadableObjectClass<any>[];
        initialObjects: {};
    }

    a ContainerSchema record to use in a Fluid container

    - -
      -
    • -
      dynamicObjectTypes: LoadableObjectClass<any>[]
    • -
    • -
      initialObjects: {}
      -
    -
    - -
      - -
    • -
      -

      See

      IFluidTurboClient.getDDS

      -
      -
      -

      Type Parameters

      -
        -
      • -

        T extends IFluidLoadable = FluidObject<any> & IFluidLoadable

      -
      -

      Parameters

      -
        -
      • -
        objectKey: string
      • -
      • -
        objectClass: LoadableObjectClass<T>
      • -
      • -
        Optional onDidFirstInitialize: ((dds) => void)
        -
          -
        • -
            -
          • (dds): void
          • -
          • -
            -

            Parameters

            -
              -
            • -
              dds: T
            -

            Returns void

      -

      Returns Promise<T>

    -
    - -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/_microsoft_live_share_turbo.DynamicObjectManager.html b/docs/classes/_microsoft_live_share_turbo.DynamicObjectManager.html deleted file mode 100644 index b039f02ec..000000000 --- a/docs/classes/_microsoft_live_share_turbo.DynamicObjectManager.html +++ /dev/null @@ -1,432 +0,0 @@ -DynamicObjectManager | Microsoft Live Share SDK
    -
    - -
    -
    -
    - -
    -

    Fluid DataObject used in FluidTurboClient for the purposes of dynamically loading DDSes.

    - -

    Remarks

    If a DDS does not yet exist for a given key, a new one is created. Fluid ConsensusRegisterCollection is used to ensure that only one person will create the DDS.

    -
    -
    -

    Hierarchy

    -
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    - -
    -
    -

    Properties

    -
    - -
    TypeName: "@microsoft/live-share:DynamicObjectManager" = ...
    -

    The objects fluid type/name.

    -
    -
    - -
    factory: DataObjectFactory<DynamicObjectManager, DataObjectTypes> = ...
    -

    The objects fluid type factory.

    -
    -
    -

    Accessors

    -
    - -
      -
    • get initializeState(): LiveDataObjectInitializeState
    • -
    • -

      The initialization status of the data object.

      - -

      Remarks

      Used to know whether it is safe to call .initialize()

      -
      -

      Returns LiveDataObjectInitializeState

    • -
    • set initializeState(value): void
    • -
    • -
      -

      Parameters

      -
      -

      Returns void

    -
    - -
      -
    • get isInitialized(): boolean
    • -
    • -

      Flag that indicates whether initialization has succeeded or not.

      - -

      Remarks

      This field is true when initializeState is succeeded, or false when initializeState is any other value.

      -
      -

      Returns boolean

    -
    -

    Methods

    -
    - -
      - -
    • -

      Get the client info for a given clientId

      -
      -
      -

      Parameters

      -
        -
      • -
        clientId: string
        -

        Fluid clientId we are requesting user info for

        -
      -

      Returns Promise<undefined | IClientInfo>

      IClientInfo object if the user is known, otherwise it will return undefined

      -
    -
    - -
      - -
    • -

      Dynamically loads a Fluid object. If one does not exist, a new one will be created.

      -
      -
      -

      Type Parameters

      -
        -
      • -

        T extends IFluidLoadable = FluidObject<any> & IFluidLoadable

        -

        Type of Fluid object to load.

        -
      -
      -

      Parameters

      -
        -
      • -
        key: string
        -

        unique key for the dynamic object

        -
      • -
      • -
        loadableClass: LoadableObjectClass<T>
        -

        the Fluid LoadableObjectClass

        -
      • -
      • -
        container: IFluidContainer
        -

        Fluid container to load the DDS into

        -
      -

      Returns Promise<{
          created: boolean;
          dds: T;
      }>

      the DDS and whether or not it was created locally

      -
    -
    - -
      - -
    • -

      hasInitialized is run by each client as they load the DataObject. Here we use it to initialize the -task manager, listen for task assignments, and listen for changes to the dynamic objects map.

      -
      -

      Returns Promise<void>

    -
    - -
      - -
    • -

      initializingFirstTime is run only once by the first client to create the DataObject. Here we use it to -initialize the state of the DataObject.

      -
      -

      Returns Promise<void>

    -
    - -
      - -
    • -

      Verify that the user has the required roles

      -
      -

      Returns Promise<boolean>

      boolean true if user has the required roles

      -
    -
    - -
      - -
    • -

      Waits until connected and gets the most recent clientId

      -
      -

      Returns Promise<string>

      clientId

      -
    -
    - -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/_microsoft_live_share_turbo.FluidTurboClient.html b/docs/classes/_microsoft_live_share_turbo.FluidTurboClient.html deleted file mode 100644 index b0b5a95b8..000000000 --- a/docs/classes/_microsoft_live_share_turbo.FluidTurboClient.html +++ /dev/null @@ -1,379 +0,0 @@ -FluidTurboClient | Microsoft Live Share SDK
    -
    - -
    -
    -
    - -
    -

    Base class for building Fluid Turbo clients.

    - -

    Remarks

    Unlike other Fluid clients, the turbo client wraps functionality regularly exposed through an IFluidContainer. This is due to the more opinionated -nature of this package than vanilla Fluid Framework, where developers do not define a full ContainerSchema themselves and objects are loaded dynamically.

    -
    -
    -

    Hierarchy

    -
    -
    -

    Implements

    -
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    -
    -

    Accessors

    -
    -
    -

    Methods

    -
    -
    -

    Constructors

    -
    - -
    -
    -

    Accessors

    -
    - -
      -
    • get canSendBackgroundUpdates(): boolean
    • -
    • -

      Setting for whether LiveDataObject instances using LiveObjectSynchronizer can send background updates. -Default value is true.

      - -

      Remarks

      This is useful for scenarios where there are a large number of participants in a session, since service performance degrades as more socket connections are opened. -Intended for use when a small number of users are intended to be "in control", such as the LiveFollowMode class's startPresenting() feature. -There should always be at least one user in the session that has canSendBackgroundUpdates set to true. -Set to true when the user is eligible to send background updates (e.g., "in control"), or false when that user is not in control. -This setting will not prevent the local user from explicitly changing the state of objects using LiveObjectSynchronizer, such as .set() in LiveState. -Impacts background updates of LiveState, LivePresence, LiveTimer, and LiveFollowMode.

      -
      -

      Returns boolean

    • -
    • set canSendBackgroundUpdates(value): void
    • -
    • -
      -

      Parameters

      -
        -
      • -
        value: boolean
      -

      Returns void

    -
    - -
      -
    • get results(): undefined | {
          container: IFluidContainer;
          services: AzureContainerServices;
      }
    • -
    • -

      Get the Fluid join container results

      -
      -

      Returns undefined | {
          container: IFluidContainer;
          services: AzureContainerServices;
      }

    -
    - -
    -
    -

    Methods

    -
    - -
      - -
    • -

      Get the container schema to use within a FluidTurboClient container.

      -
      -
      -

      Parameters

      -
        -
      • -
        Optional initialObjects: LoadableObjectClassRecord
        -

        Optional. Initial objects to add to the schema

        -
      -

      Returns {
          dynamicObjectTypes: LoadableObjectClass<any>[];
          initialObjects: {};
      }

      a ContainerSchema record to use in a Fluid container

      - -
        -
      • -
        dynamicObjectTypes: LoadableObjectClass<any>[]
      • -
      • -
        initialObjects: {}
        -
      -
      - -
        - -
      • -
        -

        See

        IFluidTurboClient.getDDS

        -
        -
        -

        Type Parameters

        -
          -
        • -

          T extends IFluidLoadable = FluidObject<any> & IFluidLoadable

        -
        -

        Parameters

        -
          -
        • -
          objectKey: string
        • -
        • -
          objectClass: LoadableObjectClass<T>
        • -
        • -
          Optional onDidFirstInitialize: ((dds) => void)
          -
            -
          • -
              -
            • (dds): void
            • -
            • -
              -

              Parameters

              -
                -
              • -
                dds: T
              -

              Returns void

        -

        Returns Promise<T>

      -
      - -
      -
      -

      Generated using TypeDoc

      -
      \ No newline at end of file diff --git a/docs/classes/_microsoft_live_share_turbo.LiveShareTurboClient.html b/docs/classes/_microsoft_live_share_turbo.LiveShareTurboClient.html deleted file mode 100644 index a964d907d..000000000 --- a/docs/classes/_microsoft_live_share_turbo.LiveShareTurboClient.html +++ /dev/null @@ -1,465 +0,0 @@ -LiveShareTurboClient | Microsoft Live Share SDK
      -
      - -
      -
      -
      - -
      -

      The FluidTurboClient implementation for the LiveShareClient.

      - -

      See

      FluidTurboClient

      -
      -
      -

      Hierarchy

      -
      -
      -
      -
      - -
      -
      -

      Constructors

      -
      - -
      -
      -

      Accessors

      -
      - -
        -
      • get canSendBackgroundUpdates(): boolean
      • -
      • -

        Setting for whether LiveDataObject instances using LiveObjectSynchronizer can send background updates. -Default value is true.

        - -

        Remarks

        This is useful for scenarios where there are a large number of participants in a session, since service performance degrades as more socket connections are opened. -Intended for use when a small number of users are intended to be "in control", such as the LiveFollowMode class's startPresenting() feature. -Set to true when the user is eligible to send background updates (e.g., "in control"), or false when that user is not in control. -This setting will not prevent the local user from explicitly changing the state of objects using LiveObjectSynchronizer, such as .set() in LiveState. -Impacts background updates of LiveState, LivePresence, LiveTimer, and LiveFollowMode.

        -
        -

        Returns boolean

      • -
      • set canSendBackgroundUpdates(value): void
      • -
      • -
        -

        Parameters

        -
          -
        • -
          value: boolean
        -

        Returns void

      -
      - -
      -
      - -
        -
      • get maxContainerLookupTries(): number
      • -
      • -

        Number of times the client should attempt to get the ID of the container to join for the -current context.

        -
        -

        Returns number

      • -
      • set maxContainerLookupTries(value): void
      • -
      • -

        Set number of times the client should attempt to get the ID of the container to join for the -current context.

        -
        -
        -

        Parameters

        -
          -
        • -
          value: number
        -

        Returns void

      -
      - -
      -
      - -
      -
      -

      Methods

      -
      - -
        - -
      • -

        Get the container schema to use within a FluidTurboClient container.

        -
        -
        -

        Parameters

        -
          -
        • -
          Optional initialObjects: LoadableObjectClassRecord
          -

          Optional. Initial objects to add to the schema

          -
        -

        Returns {
            dynamicObjectTypes: LoadableObjectClass<any>[];
            initialObjects: {};
        }

        a ContainerSchema record to use in a Fluid container

        - -
          -
        • -
          dynamicObjectTypes: LoadableObjectClass<any>[]
        • -
        • -
          initialObjects: {}
          -
        -
        - -
          - -
        • -
          -

          See

          IFluidTurboClient.getDDS

          -
          -
          -

          Type Parameters

          -
            -
          • -

            T extends IFluidLoadable = FluidObject<any> & IFluidLoadable

          -
          -

          Parameters

          -
            -
          • -
            objectKey: string
          • -
          • -
            objectClass: LoadableObjectClass<T>
          • -
          • -
            Optional onDidFirstInitialize: ((dds) => void)
            -
              -
            • -
                -
              • (dds): void
              • -
              • -
                -

                Parameters

                -
                  -
                • -
                  dds: T
                -

                Returns void

          -

          Returns Promise<T>

        -
        - -
          - -
        • -

          Connects to the fluid container for the current teams context.

          - -

          Remarks

          The first client joining the container will create the container resulting in the -onContainerFirstCreated callback being called. This callback can be used to set the initial -state of of the containers object prior to the container being attached.

          -
          -
          -

          Parameters

          -
            -
          • -
            Optional initialObjects: LoadableObjectClassRecord
            -

            Optional. Fluid ContainerSchema initialObjects.

            -
          • -
          • -
            Optional onContainerFirstCreated: ((container) => void)
            -

            Optional. Callback that's called when the container is first created.

            -
            -
              -
            • -
                -
              • (container): void
              • -
              • -
                -

                Parameters

                -
                  -
                • -
                  container: IFluidContainer
                -

                Returns void

          -

          Returns Promise<ILiveShareJoinResults>

          The fluid container and services objects to use along with a created flag that if true means the container had to be created.

          -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/enums/_microsoft_live_share.ContainerState.html b/docs/enums/_microsoft_live_share.ContainerState.html deleted file mode 100644 index 45e1eec08..000000000 --- a/docs/enums/_microsoft_live_share.ContainerState.html +++ /dev/null @@ -1,261 +0,0 @@ -ContainerState | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        State of the current Live Share sessions backing fluid container.

        -
        -
        -
        -
        - -
        -
        -

        Enumeration Members

        -
        -
        -

        Enumeration Members

        -
        - -
        added: "Added"
        -

        The call to LiveShareHost.setContainerId() successfully created the container mapping -for the current Live Share session.

        -
        -
        - -
        alreadyExists: "AlreadyExists"
        -

        A container mapping for the current Live Share Session already exists and should be used -when joining the sessions Fluid container.

        -
        -
        - -
        conflict: "Conflict"
        -

        The call to LiveShareHost.setContainerId() failed to create the container mapping due to -another client having already set the container ID for the current Live Share session.

        -
        -
        - -
        notFound: "NotFound"
        -

        A container mapping for the current Live Share session doesn't exist yet.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/enums/_microsoft_live_share.FollowModeType.html b/docs/enums/_microsoft_live_share.FollowModeType.html deleted file mode 100644 index 09eb8ecf8..000000000 --- a/docs/enums/_microsoft_live_share.FollowModeType.html +++ /dev/null @@ -1,289 +0,0 @@ -FollowModeType | Microsoft Live Share SDK
        -
        - -
        -
        -
        -
        - -

        Enumeration FollowModeTypeBeta

        -
        -

        The follow mode type.

        - -

        Remarks

        Determines which user's stateValue is being referenced by LiveFollowMode's state.value field. -Use to tell the user the current state of follow mode (e.g., "You are actively presenting"). -Use to determine any relevant button(s) to show to the user (e.g., "Stop presenting").

        -
        -
        -
        -
        - -
        -
        -

        Enumeration Members

        -
        - -
        activeFollowers: "activeFollowers"
        -

        Local user is being followed by other remote users.

        -
        -
        - -
        activePresenter: "activePresenter"
        -

        Local user is actively presenting to other users.

        -
        -
        - -
        followPresenter: "followPresenter"
        -

        Local user is following the presenter and is in sync.

        -
        -
        - -
        followUser: "followUser"
        -

        Local user is following a specific user and is in sync.

        -
        -
        - -
        local: "local"
        -

        Local user is not following anyone, there is no presenter, and nobody is following them.

        -
        -
        - -
        suspendFollowPresenter: "suspendFollowPresenter"
        -

        The local user is suspended from the remote active presenter.

        -
        -
        - -
        suspendFollowUser: "suspendFollowUser"
        -

        The local user is suspended from following a specific user.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/enums/_microsoft_live_share.LiveDataObjectInitializeState.html b/docs/enums/_microsoft_live_share.LiveDataObjectInitializeState.html deleted file mode 100644 index d93dd97f1..000000000 --- a/docs/enums/_microsoft_live_share.LiveDataObjectInitializeState.html +++ /dev/null @@ -1,258 +0,0 @@ -LiveDataObjectInitializeState | Microsoft Live Share SDK
        -
        - -
        -
        -
        -
        - -

        Enumeration LiveDataObjectInitializeState

        -
        -

        The initialization state for the LiveDataObject class.

        -
        -
        -
        -
        - -
        -
        -

        Enumeration Members

        -
        -
        -

        Enumeration Members

        -
        - -
        fatalError: "fatalError"
        -

        The state when .initialize() has a fatal error and .initialize() is never expected to succeed

        -
        -
        - -
        needed: "needed"
        -

        The default state when .initialize() has not been called and/or a previous call to .initialize() failed

        -
        -
        - -
        pending: "pending"
        -

        The state when .initialize() has been called but has not yet succeeded

        -
        -
        - -
        succeeded: "succeeded"
        -

        The state when .initialize() has succeeded

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/enums/_microsoft_live_share.LiveEventEvents.html b/docs/enums/_microsoft_live_share.LiveEventEvents.html deleted file mode 100644 index 14d0ba74f..000000000 --- a/docs/enums/_microsoft_live_share.LiveEventEvents.html +++ /dev/null @@ -1,231 +0,0 @@ -LiveEventEvents | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Events supported by LiveEvent object.

        -
        -
        -
        -
        - -
        -
        -

        Enumeration Members

        -
        -
        -

        Enumeration Members

        -
        - -
        received: "received"
        -

        An event has been sent or received.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/enums/_microsoft_live_share.LiveFollowModeEvents.html b/docs/enums/_microsoft_live_share.LiveFollowModeEvents.html deleted file mode 100644 index 48d1f0c90..000000000 --- a/docs/enums/_microsoft_live_share.LiveFollowModeEvents.html +++ /dev/null @@ -1,240 +0,0 @@ -LiveFollowModeEvents | Microsoft Live Share SDK
        -
        - -
        -
        -
        -
        - -

        Enumeration LiveFollowModeEventsBeta

        -
        -

        Events supported by LiveFollowMode object.

        -
        -
        -
        -
        - -
        -
        -

        Enumeration Members

        -
        -
        -

        Enumeration Members

        -
        - -
        presenceChanged: "presenceChanged"
        -

        A user's presence state changed.

        -
        -
        - -
        stateChanged: "stateChanged"
        -

        The follow mode state changed.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/enums/_microsoft_live_share.LivePresenceEvents.html b/docs/enums/_microsoft_live_share.LivePresenceEvents.html deleted file mode 100644 index 9d393c50e..000000000 --- a/docs/enums/_microsoft_live_share.LivePresenceEvents.html +++ /dev/null @@ -1,231 +0,0 @@ -LivePresenceEvents | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Events supported by LivePresence object.

        -
        -
        -
        -
        - -
        -
        -

        Enumeration Members

        -
        -
        -

        Enumeration Members

        -
        - -
        presenceChanged: "presenceChanged"
        -

        The presence for the local or a remote user has changed.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/enums/_microsoft_live_share.LiveStateEvents.html b/docs/enums/_microsoft_live_share.LiveStateEvents.html deleted file mode 100644 index 487b10313..000000000 --- a/docs/enums/_microsoft_live_share.LiveStateEvents.html +++ /dev/null @@ -1,231 +0,0 @@ -LiveStateEvents | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Events supported by [LiveState` object.

        -
        -
        -
        -
        - -
        -
        -

        Enumeration Members

        -
        -
        -

        Enumeration Members

        -
        - -
        stateChanged: "stateChanged"
        -

        The objects state has changed.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/enums/_microsoft_live_share.LiveTimerEvents.html b/docs/enums/_microsoft_live_share.LiveTimerEvents.html deleted file mode 100644 index 324be2540..000000000 --- a/docs/enums/_microsoft_live_share.LiveTimerEvents.html +++ /dev/null @@ -1,267 +0,0 @@ -LiveTimerEvents | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Events supported by LiveTimer object.

        -
        -
        -
        -
        - -
        -
        -

        Enumeration Members

        -
        -
        -

        Enumeration Members

        -
        - -
        finished: "finished"
        -

        Timer has finished

        -
        -
        - -
        onTick: "onTick"
        -

        Timer has progressed

        -
        -
        - -
        paused: "paused"
        -

        Playing timer has paused

        -
        -
        - -
        played: "played"
        -

        Paused timer has resumed

        -
        -
        - -
        started: "started"
        -

        Timer has started

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/enums/_microsoft_live_share.PresenceState.html b/docs/enums/_microsoft_live_share.PresenceState.html deleted file mode 100644 index ade801731..000000000 --- a/docs/enums/_microsoft_live_share.PresenceState.html +++ /dev/null @@ -1,250 +0,0 @@ -PresenceState | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        List of possible presence states.

        -
        -
        -
        -
        - -
        -
        -

        Enumeration Members

        -
        -
        -

        Enumeration Members

        -
        - -
        away: "away"
        -

        The user is away. Applications can set this state based on the users activity.

        -
        -
        - -
        offline: "offline"
        -

        The user is offline. Automatically set for users after their client has stopped sending -updates for a period of time.

        -
        -
        - -
        online: "online"
        -

        The user is online. Default state while user has at least one client connected.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/enums/_microsoft_live_share.UserMeetingRole.html b/docs/enums/_microsoft_live_share.UserMeetingRole.html deleted file mode 100644 index 00a96f422..000000000 --- a/docs/enums/_microsoft_live_share.UserMeetingRole.html +++ /dev/null @@ -1,258 +0,0 @@ -UserMeetingRole | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Allowed roles during a meeting.

        -
        -
        -
        -
        - -
        -
        -

        Enumeration Members

        -
        -
        -

        Enumeration Members

        -
        - -
        attendee: "Attendee"
        -

        The user is a standard meeting attendee.

        -
        -
        - -
        guest: "Guest"
        -

        The user is an external guest user.

        -
        -
        - -
        organizer: "Organizer"
        -

        The user is a meeting organizer.

        -
        -
        - -
        presenter: "Presenter"
        -

        The user has presenter privileges for the meeting.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/enums/_microsoft_live_share_canvas.InkingTool.html b/docs/enums/_microsoft_live_share_canvas.InkingTool.html deleted file mode 100644 index f3e6da648..000000000 --- a/docs/enums/_microsoft_live_share_canvas.InkingTool.html +++ /dev/null @@ -1,264 +0,0 @@ -InkingTool | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Defines available inking tools.

        -
        -
        -
        -
        - -
        -
        -

        Enumeration Members

        -
        -
        -

        Enumeration Members

        -
        - -
        eraser: 3
        -
        - -
        highlighter: 2
        -
        - -
        laserPointer: 1
        -
        - -
        line: 5
        -
        - -
        pen: 0
        -
        - -
        pointEraser: 4
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/enums/_microsoft_live_share_canvas.StrokeEndState.html b/docs/enums/_microsoft_live_share_canvas.StrokeEndState.html deleted file mode 100644 index 44c2c45f1..000000000 --- a/docs/enums/_microsoft_live_share_canvas.StrokeEndState.html +++ /dev/null @@ -1,233 +0,0 @@ -StrokeEndState | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -
        -
        - -
        -
        -

        Enumeration Members

        -
        -
        -

        Enumeration Members

        -
        - -
        cancelled: 1
        -
        - -
        ended: 0
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/enums/_microsoft_live_share_canvas.StrokeMode.html b/docs/enums/_microsoft_live_share_canvas.StrokeMode.html deleted file mode 100644 index 35ced60c2..000000000 --- a/docs/enums/_microsoft_live_share_canvas.StrokeMode.html +++ /dev/null @@ -1,240 +0,0 @@ -StrokeMode | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Stroke modes.

        -
        -
        -
        -
        - -
        -
        -

        Enumeration Members

        -
        -
        -

        Enumeration Members

        -
        - -
        freeHand: 0
        -

        A freehand stroke that follows a path.

        -
        -
        - -
        line: 1
        -

        A straight line stroke between two points.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/enums/_microsoft_live_share_canvas.StrokeType.html b/docs/enums/_microsoft_live_share_canvas.StrokeType.html deleted file mode 100644 index c794259d6..000000000 --- a/docs/enums/_microsoft_live_share_canvas.StrokeType.html +++ /dev/null @@ -1,251 +0,0 @@ -StrokeType | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Stroke types.

        -
        -
        -
        -
        - -
        -
        -

        Enumeration Members

        -
        -
        -

        Enumeration Members

        -
        - -
        ephemeral: 1
        -

        Ephemeral stroke, which vanishes all at once after -a set amount of time.

        -
        -
        - -
        laserPointer: 0
        -

        Laser pointer stroke, with a vanishing tail.

        -
        -
        - -
        persistent: 2
        -

        Persistent stroke, that remains on the canvas until -erased.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/enums/_microsoft_live_share_media.LimitLevelType.html b/docs/enums/_microsoft_live_share_media.LimitLevelType.html deleted file mode 100644 index 569fe438c..000000000 --- a/docs/enums/_microsoft_live_share_media.LimitLevelType.html +++ /dev/null @@ -1,233 +0,0 @@ -LimitLevelType | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -
        -
        - -
        -
        -

        Enumeration Members

        -
        -
        -

        Enumeration Members

        -
        - -
        fixed: 0
        -
        - -
        percentage: 1
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/enums/_microsoft_live_share_media.MediaPlayerSynchronizerEvents.html b/docs/enums/_microsoft_live_share_media.MediaPlayerSynchronizerEvents.html deleted file mode 100644 index d3d29648d..000000000 --- a/docs/enums/_microsoft_live_share_media.MediaPlayerSynchronizerEvents.html +++ /dev/null @@ -1,243 +0,0 @@ -MediaPlayerSynchronizerEvents | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Events supported by MediaPlayerSynchronizer object.

        -
        -
        -
        -
        - -
        -
        -

        Enumeration Members

        -
        -
        -

        Enumeration Members

        -
        - -
        coordinatorstatechange: "coordinatorstatechange"
        -
        - -
        groupaction: "groupaction"
        -
        - -
        useraction: "useraction"
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/enums/_microsoft_live_share_media.MediaSessionCoordinatorEvents.html b/docs/enums/_microsoft_live_share_media.MediaSessionCoordinatorEvents.html deleted file mode 100644 index 4044e8e15..000000000 --- a/docs/enums/_microsoft_live_share_media.MediaSessionCoordinatorEvents.html +++ /dev/null @@ -1,240 +0,0 @@ -MediaSessionCoordinatorEvents | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Event types of LiveMediaSessionCoordinator.

        -
        -
        -
        -
        - -
        -
        -

        Enumeration Members

        -
        -
        -

        Enumeration Members

        -
        - -
        coordinatorstatechange: "coordinatorstatechange"
        -

        Event emitted after the coordinator's state changed

        -
        -
        - -
        triggeraction: "triggeraction"
        -

        Event emitted when an action was triggered.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/functions/_microsoft_live_share.getLiveShareContainerSchemaProxy.html b/docs/functions/_microsoft_live_share.getLiveShareContainerSchemaProxy.html deleted file mode 100644 index 4d1ac5f00..000000000 --- a/docs/functions/_microsoft_live_share.getLiveShareContainerSchemaProxy.html +++ /dev/null @@ -1,228 +0,0 @@ -getLiveShareContainerSchemaProxy | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -
          - -
        • -

          Inject Live Share dependencies into your Fluid container schema. -This should only be done once, right before connecting to a container.

          - -

          Remarks

          Users should not use this method if you are connecting to a container using LiveShareClient. -This is intended to be used when you are using another Fluid client, such as AzureClient.

          -
          -
          -

          Parameters

          -
            -
          • -
            schema: ContainerSchema
            -

            Fluid ContainerSchema you would like to inject the runtime into

            -
          • -
          • -
            liveRuntime: LiveShareRuntime
            -

            LiveShareRuntime instance

            -
          -

          Returns ContainerSchema

          ContainerSchema with injected dependencies

          -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/functions/_microsoft_live_share_canvas.combineRects.html b/docs/functions/_microsoft_live_share_canvas.combineRects.html deleted file mode 100644 index 00aff7923..000000000 --- a/docs/functions/_microsoft_live_share_canvas.combineRects.html +++ /dev/null @@ -1,217 +0,0 @@ -combineRects | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/functions/_microsoft_live_share_canvas.darkenColor.html b/docs/functions/_microsoft_live_share_canvas.darkenColor.html deleted file mode 100644 index f3cd6297a..000000000 --- a/docs/functions/_microsoft_live_share_canvas.darkenColor.html +++ /dev/null @@ -1,224 +0,0 @@ -darkenColor | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -
          - -
        • -

          Darkens the given color by a certain intensity.

          -
          -
          -

          Parameters

          -
            -
          • -
            color: IColor
            -

            The color to darken.

            -
          • -
          • -
            intensity: number
            -

            The intensity of the darkening. Must be between 0 and 100.

            -
          -

          Returns IColor

          The darkened color.

          -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/functions/_microsoft_live_share_canvas.expandRect.html b/docs/functions/_microsoft_live_share_canvas.expandRect.html deleted file mode 100644 index 0cbc951ca..000000000 --- a/docs/functions/_microsoft_live_share_canvas.expandRect.html +++ /dev/null @@ -1,224 +0,0 @@ -expandRect | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -
          - -
        • -

          Expands the specified rectangle so it contains the specified point.

          -
          -
          -

          Parameters

          -
            -
          • -
            rect: IRect
            -

            The rectangle to extend.

            -
          • -
          • -
            point: IPoint
            -

            The point to extend the rectangle to.

            -
          -

          Returns IRect

          The expanded rectangle.

          -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/functions/_microsoft_live_share_canvas.fromCssColor.html b/docs/functions/_microsoft_live_share_canvas.fromCssColor.html deleted file mode 100644 index 167235190..000000000 --- a/docs/functions/_microsoft_live_share_canvas.fromCssColor.html +++ /dev/null @@ -1,221 +0,0 @@ -fromCssColor | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -
          - -
        • -

          Converts a CSS color expressed in the #RRGGBB format into an IColor object

          -
          -
          -

          Parameters

          -
            -
          • -
            color: string
            -

            The CSS color to convert.

            -
          -

          Returns IColor

          The converted color as an IColor object, or a default color if the provided -color string isn't valid.

          -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/functions/_microsoft_live_share_canvas.getDistanceBetweenPoints.html b/docs/functions/_microsoft_live_share_canvas.getDistanceBetweenPoints.html deleted file mode 100644 index 1ec0f10ef..000000000 --- a/docs/functions/_microsoft_live_share_canvas.getDistanceBetweenPoints.html +++ /dev/null @@ -1,224 +0,0 @@ -getDistanceBetweenPoints | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -
          - -
        • -

          Computes the distance between two points.

          -
          -
          -

          Parameters

          -
            -
          • -
            p1: IPoint
            -

            The first point.

            -
          • -
          • -
            p2: IPoint
            -

            The second point.

            -
          -

          Returns number

          The distance between p1 and p2.

          -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/functions/_microsoft_live_share_canvas.getPressureAdjustedSize.html b/docs/functions/_microsoft_live_share_canvas.getPressureAdjustedSize.html deleted file mode 100644 index bdec876a8..000000000 --- a/docs/functions/_microsoft_live_share_canvas.getPressureAdjustedSize.html +++ /dev/null @@ -1,224 +0,0 @@ -getPressureAdjustedSize | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -
          - -
        • -

          Adjusts a size given a pointer pressure.

          -
          -
          -

          Parameters

          -
            -
          • -
            baseSize: number
            -

            The size to adjust.

            -
          • -
          • -
            pressure: number
            -

            The pressure.

            -
          -

          Returns number

          The adjusted size.

          -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/functions/_microsoft_live_share_canvas.getSquaredDistanceBetweenPoints.html b/docs/functions/_microsoft_live_share_canvas.getSquaredDistanceBetweenPoints.html deleted file mode 100644 index 7eebe7abd..000000000 --- a/docs/functions/_microsoft_live_share_canvas.getSquaredDistanceBetweenPoints.html +++ /dev/null @@ -1,225 +0,0 @@ -getSquaredDistanceBetweenPoints | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -
          - -
        • -

          Computes the square of the distance between two points. This provides a cheaper -way to compare multiple distances since it doesn't compute any square root.

          -
          -
          -

          Parameters

          -
            -
          • -
            p1: IPoint
            -

            The first point.

            -
          • -
          • -
            p2: IPoint
            -

            The second point.

            -
          -

          Returns number

          The square of the distance between p1 and p2.

          -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/functions/_microsoft_live_share_canvas.lightenColor.html b/docs/functions/_microsoft_live_share_canvas.lightenColor.html deleted file mode 100644 index a8ec75a04..000000000 --- a/docs/functions/_microsoft_live_share_canvas.lightenColor.html +++ /dev/null @@ -1,224 +0,0 @@ -lightenColor | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -
          - -
        • -

          Lightens the given color by a certain intensity.

          -
          -
          -

          Parameters

          -
            -
          • -
            color: IColor
            -

            The color to lighten.

            -
          • -
          • -
            intensity: number
            -

            The intensity of the lightening. Must be between 0 and 100.

            -
          -

          Returns IColor

          The lightened color.

          -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/functions/_microsoft_live_share_canvas.screenToViewport.html b/docs/functions/_microsoft_live_share_canvas.screenToViewport.html deleted file mode 100644 index 0e32fc104..000000000 --- a/docs/functions/_microsoft_live_share_canvas.screenToViewport.html +++ /dev/null @@ -1,232 +0,0 @@ -screenToViewport | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -
          - -
        • -

          Converts screen coordinates to viewport coordinates.

          -
          -
          -

          Parameters

          -
            -
          • -
            p: IPoint
            -

            The point to convert.

            -
          • -
          • -
            viewportReferencePoint: IPoint
            -

            The videwport's reference point.

            -
          • -
          • -
            viewportOffset: IPoint
            -

            The viewport offset.

            -
          • -
          • -
            scale: number
            -

            The viewport scale. Defaults to 1 if the provided value is less than or equal to 0.

            -
          -

          Returns IPoint

          The converted point.

          -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/functions/_microsoft_live_share_canvas.toCssRgbaColor.html b/docs/functions/_microsoft_live_share_canvas.toCssRgbaColor.html deleted file mode 100644 index 7400f6b0c..000000000 --- a/docs/functions/_microsoft_live_share_canvas.toCssRgbaColor.html +++ /dev/null @@ -1,222 +0,0 @@ -toCssRgbaColor | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -
          - -
        • -

          Converts an IColor object into its CSS rgba() representation.

          -
          -
          -

          Parameters

          -
            -
          • -
            color: IColor
            -

            The color to convert.

            -
          • -
          • -
            alpha: number = 1
          -

          Returns string

          A string representing the CSS rgba() representation of the color.

          -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/functions/_microsoft_live_share_canvas.viewportToScreen.html b/docs/functions/_microsoft_live_share_canvas.viewportToScreen.html deleted file mode 100644 index 91482955f..000000000 --- a/docs/functions/_microsoft_live_share_canvas.viewportToScreen.html +++ /dev/null @@ -1,232 +0,0 @@ -viewportToScreen | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -
          - -
        • -

          Converts viewport coordinates to screen coordinates.

          -
          -
          -

          Parameters

          -
            -
          • -
            p: IPoint
            -

            The point to convert.

            -
          • -
          • -
            viewportReferencePoint: IPoint
            -

            The viewport's reference point.

            -
          • -
          • -
            viewportOffset: IPoint
            -

            The viewport offset.

            -
          • -
          • -
            scale: number
            -

            The viewport scale. Defaults to 1 if the provided value is less than or equal to 0.

            -
          -

          Returns IPoint

          The converted point.

          -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index 6d6c3fa1c..000000000 --- a/docs/index.html +++ /dev/null @@ -1,382 +0,0 @@ -Microsoft Live Share SDK
        -
        - -
        -
        -
        -
        -

        Microsoft Live Share SDK

        -

        Live Share SDK

        The Live Share SDK builds on the Fluid Framework to enable the creation of collaborative experiences for Microsoft Teams and Microsoft 365. This package focuses on building collaborative meeting applications for Microsoft Teams using Fluid. The SDK provides a LiveShareClient class for connecting to a special Fluid Container associated with each meeting. A collection of Live Share specific Distributed Data Structure (DDS) classes are also provided to simplify building applications for common meeting scenarios like shared media playback.

        -

        To get started, we recommend first familiarizing yourself with the Fluid Framework and Live Share overview. You can then follow our Quick Start Guide to build your first Teams Meeting App that uses Live Share.

        -

        You can find our detailed API reference documentation at Live Share reference docs and Live Share Media reference docs.

        -

        Collaborative features

        Live Share has several features that make building collaborative apps easier than ever, including:

        -
          -
        • LiveShareClient: Connect to a Fluid container associated with a Microsoft Teams meeting.
        • -
        • LivePresence: Track who is using your app during a meeting and associate custom metadata for each user (e.g., camera position).
        • -
        • LiveState: Synchronize a JSON-serializable value for maintaining consistent application state across clients.
        • -
        • LiveTimer: Build a collaborative countdown timer.
        • -
        • LiveEvent: Send one-time, stateless JSON-serializable values to each user in the session.
        • -
        • LiveFollowMode (beta): Easily integrate features to present to all, follow specific users, and suspend/resume following.
        • -
        -

        Live Share Canvas is an optional extension that allows any app to add a collaborative whiteboard as an app overlay. Key classes include:

        -
          -
        • InkingManager: Utilizes the HTML <canvas> element for turn-key pen, highlighter, laser pointer, and eraser tools.
        • -
        • LiveCanvas: Synchronizes the InkingManager strokes and adds remote cursors for users in the session.
        • -
        -

        Live Share Media is an optional extension that makes it easy to add co-watch support to any video or audio player. Key classes include:

        -
          -
        • LiveMediaSession: Synchronizes player state for everyone in the session.
        • -
        • MediaPlayerSynchronizer: Delegate interface used with LiveMediaSession to execute playback commands against a media player; matches the HTML5 IMediaPlayer interface for <video> or <audio> elements.
        • -
        -

        Live Share React (beta) is an optional integration for React, providing a <LiveShareProvider> context provider component and a series of custom React hooks that correspond with each Live Share and Fluid DDS.

        -

        Fluid Framework also offers some useful collaborative features, each of which is compatible with Live Share, including:

        -
          -
        • SharedMap: The DDS equivalent to a JavaScript Map, which is useful for synchronizing a collection of objects.
        • -
        • SharedString: Synchronize a string text value, useful for building real-time text editors.
        • -
        • SharedTree (alpha): Synchronize a complex tree of intersecting nodes.
        • -
        -

        Package Compatibility

        The Live Share SDK contains dependencies for @microsoft/teams-js and fluid-framework packages among others. Both of these packages are sensitive to the package version your app any libraries use. You will likely run into issues if the package version your app uses doesn't match the version other libraries you depend on use.

        -

        It is critical that your app use the package dependencies listed in the table below. Lookup the version of the @microsoft/live-share you're using and set any other dependencies in your package.json file to match:

        - - - - - - - - - - - - - - - - - - - - - -
        @microsoft/live-share@microsoft/teams-jsfluid-framework@microsoft/live-share-*@fluidframework/azure-client@microsoft/TeamsFx@microsoft/TeamsFx-react
        ^1.0.0^2.11.0^1.2.3^1.0.0^1.0.0^2.5.0^2.5.0
        -

        Installing

        Live Share

        To add the latest version of the SDK to your application using NPM:

        -
        npm install fluid-framework @fluidframework/azure-client @microsoft/live-share --save
        -
        -

        or using Yarn:

        -
        yarn add fluid-framework @fluidframework/azure-client @microsoft/live-share
        -
        -

        Live Share Media

        Optionally, to add the latest version of the media package to your application using NPM:

        -
        npm install @microsoft/live-share-media --save
        -
        -

        or using Yarn:

        -
        yarn add @microsoft/live-share-media
        -
        -

        Live Share Canvas

        Optionally, to add the latest version of the canvas package (inking & cursors) to your application using NPM:

        -
        npm install @microsoft/live-share-canvas --save
        -
        -

        or using Yarn:

        -
        yarn add @microsoft/live-share-canvas
        -
        -

        Live Share integration with React

        Optionally, to add the latest version of the React integration to your application using NPM:

        -
        npm install @microsoft/live-share-react --save
        -
        -

        or using Yarn:

        -
        yarn add @microsoft/live-share-react
        -
        -

        Contributing

        There are several ways you can contribute to this project:

        - -

        This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.

        -

        Preparing the Repository

        To clone the repository to test samples and/or build the packages, ensure that you have the latest versions of Git and Node.js installed.

        -

        Clone a copy of the repo:

        -
        git clone https://github.com/microsoft/live-share-sdk.git
        -
        -

        Change to the live-share-sdk directory:

        -
        cd live-share-sdk
        -
        -

        Building Packages & Samples

        To build the projects packages (with symlinks to the locally built packages), we use npm workspaces to prevent dependency errors.

        -

        Install all developer dependencies:

        -
        npm install
        -
        -

        Build packages and samples:

        -
        npm run build
        -
        -

        Run the sample of of your choice:

        -
        cd samples/javascript/01.dice-roller
        npm start -
        -

        Unit tests for all of the packages can be run using npm run test or npm run test:debug. Any previously built files can be deleted prior to building by first running npm run clean.

        -

        Code samples

        There are several code samples available to use:

        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        Sample nameDescriptionJavascriptTypeScript
        Dice RollerEnable all connected clients to roll a dice and view the result.ViewView
        React VideoBasic example showing how the LiveMediaSession class works with HTML5 video.View
        Live Canvas demoSynchronized pens, laser pointers, cursors, and more via Live Share Canvas.ViewView
        Live Share React demoExample of using the Live Share React package.ViewView
        React Media TemplateEnable all connected clients to watch videos together, build a shared playlist, transfer whom is in control, and annotate over the video.ViewView
        Agile PokerEnable all connected clients to play an Agile Poker planning activity.View
        -

        Reporting Security Issues

        Security issues and bugs should be reported privately, via email, to the Microsoft Security Response Center (MSRC) at secure@microsoft.com. You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Further information, including the MSRC PGP key, can be found in the Security TechCenter.

        -

        Licensing & Copyright

        Copyright (c) Microsoft Corporation. All rights reserved.

        -

        Live Share, Live Share media, and Live Share canvas are licensed under a special Microsoft Live Share SDK license.

        -

        Live Share Turbo and Live Share React are licensed under a special Microsoft Live Share SDK - Pre-Release Version license.

        -

        Code samples are licensed separately under MIT license.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share.IClientInfo.html b/docs/interfaces/_microsoft_live_share.IClientInfo.html deleted file mode 100644 index d5e93ff52..000000000 --- a/docs/interfaces/_microsoft_live_share.IClientInfo.html +++ /dev/null @@ -1,254 +0,0 @@ -IClientInfo | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Returned from LiveShareHost.getClientInfo() to specify the user information for a given clientId. -Each user individually requests this data for each other user in the session, making it secure & trusted.

        -
        -
        -

        Hierarchy

        -
          -
        • IClientInfo
        -
        -
        -
        - -
        -
        -

        Properties

        -
        -
        -

        Properties

        -
        - -
        displayName?: string
        -

        Optional. The display name for the user.

        -
        -
        - - -

        List of roles of the user.

        -
        -
        - -
        userId: string
        -

        The user identifier that corresponds to the provided client identifier.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share.IClientTimestamp.html b/docs/interfaces/_microsoft_live_share.IClientTimestamp.html deleted file mode 100644 index 3508fd10f..000000000 --- a/docs/interfaces/_microsoft_live_share.IClientTimestamp.html +++ /dev/null @@ -1,247 +0,0 @@ -IClientTimestamp | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Base interface for all client timestamp comparisons.

        -
        -
        -

        Hierarchy

        -
        -
        -
        -
        - -
        -
        -

        Properties

        -
        -
        -

        Properties

        -
        - -
        clientId: string
        -

        Client ID for the active socket connection.

        -
        -
        - -
        timestamp: number
        -

        Global timestamp of when the event was sent.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share.IContainerRuntimeSignaler.html b/docs/interfaces/_microsoft_live_share.IContainerRuntimeSignaler.html deleted file mode 100644 index 66589944b..000000000 --- a/docs/interfaces/_microsoft_live_share.IContainerRuntimeSignaler.html +++ /dev/null @@ -1,306 +0,0 @@ -IContainerRuntimeSignaler | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Duck type of something that provides the expected signalling functionality at the container level.

        - -

        Remarks

        Simplifies the mocks needed to unit test the LiveObjectSynchronizer. Applications can -just pass this.context.containerRuntime to any class that takes an IContainerRuntimeSignaler.

        -
        -
        -

        Hierarchy

        -
          -
        • IContainerRuntimeSignaler
        -
        -
        -
        - -
        -
        -

        Methods

        -
        -
        -

        Methods

        -
        - -
        -
        - -
        -
        - -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share.IEvent.html b/docs/interfaces/_microsoft_live_share.IEvent.html deleted file mode 100644 index a80523715..000000000 --- a/docs/interfaces/_microsoft_live_share.IEvent.html +++ /dev/null @@ -1,238 +0,0 @@ -IEvent | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Base interface for all event objects.

        -
        -
        -

        Hierarchy

        -
        -
        -
        -
        - -
        -
        -

        Properties

        -
        -
        -

        Properties

        -
        - -
        name: string
        -

        Name of the event.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share.IFluidContainerInfo.html b/docs/interfaces/_microsoft_live_share.IFluidContainerInfo.html deleted file mode 100644 index a56b1f63b..000000000 --- a/docs/interfaces/_microsoft_live_share.IFluidContainerInfo.html +++ /dev/null @@ -1,267 +0,0 @@ -IFluidContainerInfo | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Returned from LiveShareHost.get/setFluidContainerId() to specify the container mapping for the -current Live Share session.

        -
        -
        -

        Hierarchy

        -
          -
        • IFluidContainerInfo
        -
        -
        -
        - -
        -
        -

        Properties

        -
        - -
        containerId: undefined | string
        -

        ID of the container to join for the meeting. Undefined if the container hasn't been -created yet.

        -
        -
        - -
        containerState: ContainerState
        -

        State of the containerId mapping.

        -
        -
        - -
        retryAfter: number
        -

        If containerId is undefined and shouldCreate is false, the container isn't ready but -another client is creating it. The local client should wait the specified amount of time and -then ask for the container info again.

        -
        -
        - -
        shouldCreate: boolean
        -

        If true, the local client should create the container and then save the created containers -ID to the mapping service.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share.IFluidTenantInfo.html b/docs/interfaces/_microsoft_live_share.IFluidTenantInfo.html deleted file mode 100644 index ee2fa3068..000000000 --- a/docs/interfaces/_microsoft_live_share.IFluidTenantInfo.html +++ /dev/null @@ -1,245 +0,0 @@ -IFluidTenantInfo | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Returned from LiveShareHost.getFluidTenantInfo() to specify the Fluid service to use for the -current Live Share session.

        -
        -
        -

        Hierarchy

        -
          -
        • IFluidTenantInfo
        -
        -
        -
        - -
        -
        -

        Properties

        -
        -
        -

        Properties

        -
        - -
        serviceEndpoint: string
        -

        The Fluid service endpoint Live Share should use.

        -
        -
        - -
        tenantId: string
        -

        The Fluid Tenant ID Live Share should use.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share.IFollowModePresenceUserData.html b/docs/interfaces/_microsoft_live_share.IFollowModePresenceUserData.html deleted file mode 100644 index a11a489db..000000000 --- a/docs/interfaces/_microsoft_live_share.IFollowModePresenceUserData.html +++ /dev/null @@ -1,251 +0,0 @@ -IFollowModePresenceUserData | Microsoft Live Share SDK
        -
        - -
        -
        -
        -
        - -

        Interface IFollowModePresenceUserData<TData>Beta

        -
        -

        The presence data for a user's personal follow mode state.

        -
        -
        -

        Type Parameters

        -
          -
        • -

          TData = any

        -
        -

        Hierarchy

        -
          -
        • IFollowModePresenceUserData
        -
        -
        -
        - -
        -
        -

        Properties

        -
        -
        -

        Properties

        -
        - -
        followingUserId: undefined | string
        -

        The user that this user is following.

        - -

        Remarks

        This will be ignored when LiveFollowMode["presentingUserIdState"] is set.

        -
        -
        - -
        stateValue: TData
        -

        User's personal state

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share.IFollowModeState.html b/docs/interfaces/_microsoft_live_share.IFollowModeState.html deleted file mode 100644 index 1159493cc..000000000 --- a/docs/interfaces/_microsoft_live_share.IFollowModeState.html +++ /dev/null @@ -1,291 +0,0 @@ -IFollowModeState | Microsoft Live Share SDK
        -
        - -
        -
        -
        -
        - -

        Interface IFollowModeState<TData>Beta

        -
        -

        Information about the state of the local user's follow mode.

        - -

        Remarks

        This includes information such as whether there is a presenting user and which user's state is relevant to the local user.

        -
        -
        -

        Type Parameters

        -
          -
        • -

          TData = any

        -
        -

        Hierarchy

        -
          -
        • IFollowModeState
        -
        -
        -
        - -
        -
        -

        Properties

        -
        - -
        followingUserId: string
        -

        The userId of the user that the user is following. -This value can be either the presenting user or a specific user the local user is following.

        - -

        Remarks

        Is a string when type is followPresenter, suspendFollowPresenter, followUser, or suspendFollowUser. -Is undefined when type is local or activePresenter. -Presenting takes precedence over following a specific user.

        -
        -
        - -
        isLocalValue: boolean
        -

        Indicates that is true when the value is referencing the local user's ["stateValue"].

        - -

        Remarks

        When true, followingUserId may not be the local user's id when type is suspendFollowUser or suspendFollowPresenter.

        -
        -
        - -
        otherUsersCount: number
        -

        Number of other non-local users following along with this current state value

        -
        -
        - - -

        The follow mode type for the local user.

        - -

        Remarks

        Determines which user's ["stateValue"] to use for value. -Calculated using a combination of different conditions, such as whether there is an active presenter.

        -
        -
        - -
        value: TData
        -

        The custom value the app should use locally to reflect the follow state.

        - -

        Remarks

        The relevant user's ["stateValue"], as determined by type. -For example, if FollowModeType is activePresenter, this value will be the actively presenting user's stateValue.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share.ILiveEvent.html b/docs/interfaces/_microsoft_live_share.ILiveEvent.html deleted file mode 100644 index 3002ab1ae..000000000 --- a/docs/interfaces/_microsoft_live_share.ILiveEvent.html +++ /dev/null @@ -1,273 +0,0 @@ -ILiveEvent | Microsoft Live Share SDK
        -
        - -
        -
        -
        -
        - -

        Interface ILiveEvent<TEvent>

        -
        -

        Base type for all incoming live share events of a certain type

        -
        -
        -

        Type Parameters

        -
          -
        • -

          TEvent = any

        -
        -

        Hierarchy

        -
        -
        -
        -
        - -
        -
        -

        Properties

        -
        -
        -

        Properties

        -
        - -
        clientId: string
        -

        Client ID for the active socket connection.

        -
        -
        - -
        data: TEvent
        -
        - -
        name: string
        -

        Name of the event.

        -
        -
        - -
        timestamp: number
        -

        Global timestamp of when the event was sent.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share.ILiveEventEvents.html b/docs/interfaces/_microsoft_live_share.ILiveEventEvents.html deleted file mode 100644 index e97b54701..000000000 --- a/docs/interfaces/_microsoft_live_share.ILiveEventEvents.html +++ /dev/null @@ -1,278 +0,0 @@ -ILiveEventEvents | Microsoft Live Share SDK
        -
        - -
        -
        -
        -
        - -

        Interface ILiveEventEvents<TEvent>

        -
        -

        Type Parameters

        -
          -
        • -

          TEvent

          -

          Type of event to broadcast.

          -
        -
        -

        Hierarchy

        -
          -
        • IEvent -
            -
          • ILiveEventEvents
        -
        -
          - -
        • -

          A remote event was received or a local event was sent.

          -
          -
          -

          Parameters

          -
            -
          • -
            event: "received"
            -

            Name of event.

            -
          • -
          • -
            listener: ((evt, local, clientId, timestamp) => void)
            -

            Function called when event is triggered.

            -
            -
              -
            • -
                -
              • (evt, local, clientId, timestamp): void
              • -
              • -
                -

                Parameters

                -
                  -
                • -
                  evt: TEvent
                • -
                • -
                  local: boolean
                • -
                • -
                  clientId: string
                • -
                • -
                  timestamp: number
                -

                Returns void

          -

          Returns any

        • - -
        • -

          Event typings for LiveEvent class.

          -
          -
          -

          Parameters

          -
            -
          • -
            event: string
          • -
          • -
            listener: ((...args) => void)
            -
              -
            • -
                -
              • (...args): void
              • -
              • -
                -

                Parameters

                -
                  -
                • -
                  Rest ...args: any[]
                -

                Returns void

          -

          Returns any

        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share.ILiveFollowModeEvents.html b/docs/interfaces/_microsoft_live_share.ILiveFollowModeEvents.html deleted file mode 100644 index 157367aed..000000000 --- a/docs/interfaces/_microsoft_live_share.ILiveFollowModeEvents.html +++ /dev/null @@ -1,309 +0,0 @@ -ILiveFollowModeEvents | Microsoft Live Share SDK
        -
        - -
        -
        -
        -
        - -

        Interface ILiveFollowModeEvents<TData>

        -
        -

        Type Parameters

        -
          -
        • -

          TData = any

          -

          Type of data object to share with clients.

          -
        -
        -

        Hierarchy

        -
        -
        -
          - -
        • -

          The presence information for the local or a remote user has changed.

          -
          -
          -

          Parameters

          -
            -
          • -
            event: "stateChanged"
            -

            Name of event.

            -
          • -
          • -
            listener: ((state, local, clientId) => void)
            -

            Function called when event is triggered.

            -
            -
              -
            • -
                -
              • (state, local, clientId): void
              • -
              • -
                -

                Parameters

                -
                -

                Returns void

          -

          Returns any

        • - -
        • -

          The presence information for the local or a remote user has changed.

          -
          -
          -

          Parameters

          -
            -
          • -
            event: "presenceChanged"
            -

            Name of event.

            -
          • -
          • -
            listener: ((user, local, clientId) => void)
            -

            Function called when event is triggered.

            -
            -
          -

          Returns any

        • - -
        • Beta -

          Event typings for LiveFollowMode class.

          -
          -
          -

          Parameters

          -
            -
          • -
            event: string
          • -
          • -
            listener: ((...args) => void)
            -
              -
            • -
                -
              • (...args): void
              • -
              • -
                -

                Parameters

                -
                  -
                • -
                  Rest ...args: any[]
                -

                Returns void

          -

          Returns any

        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share.ILivePresenceEvents.html b/docs/interfaces/_microsoft_live_share.ILivePresenceEvents.html deleted file mode 100644 index 37a902eb0..000000000 --- a/docs/interfaces/_microsoft_live_share.ILivePresenceEvents.html +++ /dev/null @@ -1,279 +0,0 @@ -ILivePresenceEvents | Microsoft Live Share SDK
        -
        - -
        -
        -
        -
        - -

        Interface ILivePresenceEvents<TData>

        -
        -

        Type Parameters

        -
          -
        • -

          TData extends object = object

          -

          Type of data object to share with clients.

          -
        -
        -

        Hierarchy

        -
        -
        -
          - -
        • -

          The presence information for the local or a remote user has changed.

          -
          -
          -

          Parameters

          -
            -
          • -
            event: "presenceChanged"
            -

            Name of event.

            -
          • -
          • -
            listener: ((user, local, clientId) => void)
            -

            Function called when event is triggered.

            -
            -
              -
            • -
                -
              • (user, local, clientId): void
              • -
              • -
                -

                Parameters

                -
                -

                Returns void

          -

          Returns any

        • - -
        • -

          Event typings for LivePresence class.

          -
          -
          -

          Parameters

          -
            -
          • -
            event: string
          • -
          • -
            listener: ((...args) => void)
            -
              -
            • -
                -
              • (...args): void
              • -
              • -
                -

                Parameters

                -
                  -
                • -
                  Rest ...args: any[]
                -

                Returns void

          -

          Returns any

        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share.ILiveShareClientOptions.html b/docs/interfaces/_microsoft_live_share.ILiveShareClientOptions.html deleted file mode 100644 index 5fdc5042e..000000000 --- a/docs/interfaces/_microsoft_live_share.ILiveShareClientOptions.html +++ /dev/null @@ -1,279 +0,0 @@ -ILiveShareClientOptions | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Options used to configure the LiveShareClient class.

        -
        -
        -

        Hierarchy

        -
          -
        • ILiveShareClientOptions
        -
        -
        -
        - -
        -
        -

        Properties

        -
        - -
        canSendBackgroundUpdates?: boolean
        -

        Optional. Setting for whether LiveDataObject instances using LiveObjectSynchronizer can send background updates. -Default value is true.

        - -

        Remarks

        This is useful for scenarios where there are a large number of participants in a session, since service performance degrades as more socket connections are opened. -Intended for use when a small number of users are intended to be "in control", such as the LiveFollowMode class's startPresenting() feature. -There should always be at least one user in the session that has canSendBackgroundUpdates set to true. -Set to true when the user is eligible to send background updates (e.g., "in control"), or false when that user is not in control. -This setting will not prevent the local user from explicitly changing the state of objects using LiveObjectSynchronizer, such as .set() in LiveState. -Impacts background updates of LiveState, LivePresence, LiveTimer, and LiveFollowMode.

        -
        -
        - -
        connection?: AzureRemoteConnectionConfig | AzureLocalConnectionConfig
        -

        Optional. Configuration to use when connecting to a custom Azure Fluid Relay instance.

        -
        -
        - -
        logger?: ITelemetryBaseLogger
        -

        Optional. A logger instance to receive diagnostic messages.

        -
        -
        - -
        roleVerifier?: IRoleVerifier
        -

        Optional. Custom role verifier to use.

        -
        -
        - -
        timestampProvider?: ITimestampProvider
        -

        Optional. Custom timestamp provider to use.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share.ILiveShareHost.html b/docs/interfaces/_microsoft_live_share.ILiveShareHost.html deleted file mode 100644 index 800f6bf69..000000000 --- a/docs/interfaces/_microsoft_live_share.ILiveShareHost.html +++ /dev/null @@ -1,380 +0,0 @@ -ILiveShareHost | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Interface for hosting a Live Share session within a client like Teams.

        -
        -
        -

        Hierarchy

        -
          -
        • ILiveShareHost
        -
        -

        Implemented by

        -
        -
        -
        -
        - -
        -
        -

        Methods

        -
        - -
          - -
        • -

          Queries the hosts IClientInfo for a given client ID.

          -
          -
          -

          Parameters

          -
            -
          • -
            clientId: string
            -

            ID of the client to lookup.

            -
          -

          Returns Promise<undefined | IClientInfo>

          IUserInfo for the queried client ID, or undefined if the client hasn't yet been registered

          -
        -
        - -
          - -
        • -
          -

          Deprecated

          Queries the hosts role verification service for the roles associated with a given client ID.

          -
          -
          -

          Parameters

          -
            -
          • -
            clientId: string
            -

            ID of teh client to lookup.

            -
          -

          Returns Promise<undefined | UserMeetingRole[]>

          An array of roles assigned to the queried client ID.

          -
        -
        - -
        -
        - -
        -
        - -
          - -
        • -

          Returns the Fluid access token to use for the current session.

          -
          -
          -

          Parameters

          -
            -
          • -
            Optional containerId: string
            -

            Optional. ID of the container being joined. This will be undefined when creating a new container.

            -
          -

          Returns Promise<string>

        -
        - -
        -
        - -
          - -
        • -

          Registers the local clients Fluid client ID with the hosts role verification service.

          - -

          Remarks

          Hosts should expect this to be called anytime the Fluid clients underlying socket connects -or reconnects.

          -
          -
          -

          Parameters

          -
            -
          • -
            clientId: string
            -

            Unique ID assigned to the local Fluid client.

            -
          -

          Returns Promise<UserMeetingRole[]>

          An array of meeting roles assigned to the local user.

          -
        -
        - -
          - -
        • -

          Attempts to save the ID of the Fluid container created to the hosts mapping service.

          - -

          Remarks

          Hosts should return a containerState of "Added" if the mapping was successfully saved, -otherwise a state of "Conflict" should be returned to indicate that another client has -already saved a container ID for the current session.

          -
          -
          -

          Parameters

          -
            -
          • -
            containerId: string
            -

            Id of the Fluid container that was created.

            -
          -

          Returns Promise<IFluidContainerInfo>

          Information indicating the success of mapping assignment.

          -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share.ILiveShareJoinResults.html b/docs/interfaces/_microsoft_live_share.ILiveShareJoinResults.html deleted file mode 100644 index 5e47a926c..000000000 --- a/docs/interfaces/_microsoft_live_share.ILiveShareJoinResults.html +++ /dev/null @@ -1,263 +0,0 @@ -ILiveShareJoinResults | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Response object from .joinContainer() in LiveShareClient

        -
        -
        -

        Hierarchy

        -
          -
        • ILiveShareJoinResults
        -
        -
        -
        - -
        -
        -

        Properties

        -
        - -
        container: IFluidContainer
        -

        Fluid container

        -
        -
        - -
        created: boolean
        -

        Whether the local user was the one to create the container

        -
        -
        - -
        services: AzureContainerServices
        -

        Azure Container Services, which includes things like Fluid Audience

        -
        -
        - -
        timestampProvider: ITimestampProvider
        -

        Live Share timestamp provider. Can be used to .getTimestamp() for a global clock value. -This reference timestamp value should be fairly consistent for all users in the session.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share.ILiveStateEvents.html b/docs/interfaces/_microsoft_live_share.ILiveStateEvents.html deleted file mode 100644 index d50786ff6..000000000 --- a/docs/interfaces/_microsoft_live_share.ILiveStateEvents.html +++ /dev/null @@ -1,278 +0,0 @@ -ILiveStateEvents | Microsoft Live Share SDK
        -
        - -
        -
        -
        -
        - -

        Interface ILiveStateEvents<TState>

        -
        -

        Type Parameters

        -
          -
        • -

          TState = any

          -

          State object that's synchronized with the state.

          -
        -
        -

        Hierarchy

        -
          -
        • IEvent -
            -
          • ILiveStateEvents
        -
        -
          - -
        • -

          An LiveState objects state has changed.

          -
          -
          -

          Parameters

          -
            -
          • -
            event: "stateChanged"
            -

            Name of event.

            -
          • -
          • -
            listener: ((state, local, clientId, timestamp) => void)
            -

            Function called when event is triggered.

            -
            -
              -
            • -
                -
              • (state, local, clientId, timestamp): void
              • -
              • -
                -

                Parameters

                -
                  -
                • -
                  state: TState
                • -
                • -
                  local: boolean
                • -
                • -
                  clientId: string
                • -
                • -
                  timestamp: number
                -

                Returns void

          -

          Returns any

        • - -
        • -

          Event typings for LiveState class.

          -
          -
          -

          Parameters

          -
            -
          • -
            event: string
          • -
          • -
            listener: ((...args) => void)
            -
              -
            • -
                -
              • (...args): void
              • -
              • -
                -

                Parameters

                -
                  -
                • -
                  Rest ...args: any[]
                -

                Returns void

          -

          Returns any

        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share.ILiveTelemetryProperties.html b/docs/interfaces/_microsoft_live_share.ILiveTelemetryProperties.html deleted file mode 100644 index c2c9e86dd..000000000 --- a/docs/interfaces/_microsoft_live_share.ILiveTelemetryProperties.html +++ /dev/null @@ -1,266 +0,0 @@ -ILiveTelemetryProperties | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Properties included on all events sent by LiveTelemetryLogger.

        -
        -
        -

        Hierarchy

        -
          -
        • ITelemetryProperties -
            -
          • ILiveTelemetryProperties
        -
        -
        -
        - -
        -
        -

        Properties

        -
        - -
        clientId?: string
        -

        Optional. ID of the client if it's been assigned by the runtime.

        -
        -
        - -
        correlationId: string
        -

        ID used to correlate multiple events for an operation. Typically of the form of -${clientId}:${timestamp} but may include the clientId of the sender when logging -that an event was received.

        -
        -
        - -
        eventName: string
        -

        Name of the event being logged.

        -
        -
        - -
        timestamp: string
        -

        Time that the event occurred. The timestamp is generated by _liveRuntime.getTimestamp.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share.ILiveTimerEvents.html b/docs/interfaces/_microsoft_live_share.ILiveTimerEvents.html deleted file mode 100644 index 36532deba..000000000 --- a/docs/interfaces/_microsoft_live_share.ILiveTimerEvents.html +++ /dev/null @@ -1,355 +0,0 @@ -ILiveTimerEvents | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Hierarchy

        -
          -
        • IEvent -
            -
          • ILiveTimerEvents
        -
        -
          - -
        • -
          -

          Parameters

          -
            -
          • -
            event: "started"
          • -
          • -
            listener: ((config, local) => void)
            -
              -
            • -
                -
              • (config, local): void
              • -
              • -
                -

                Parameters

                -
                -

                Returns void

          -

          Returns any

        • - -
        • -
          -

          Parameters

          -
            -
          • -
            event: "played"
          • -
          • -
            listener: ((config, local) => void)
            -
              -
            • -
                -
              • (config, local): void
              • -
              • -
                -

                Parameters

                -
                -

                Returns void

          -

          Returns any

        • - -
        • -
          -

          Parameters

          -
            -
          • -
            event: "paused"
          • -
          • -
            listener: ((config, local) => void)
            -
              -
            • -
                -
              • (config, local): void
              • -
              • -
                -

                Parameters

                -
                -

                Returns void

          -

          Returns any

        • - -
        • -
          -

          Parameters

          -
            -
          • -
            event: "finished"
          • -
          • -
            listener: ((config) => void)
            -
              -
            • -
                -
              • (config): void
              • -
              • -
                -

                Parameters

                -
                -

                Returns void

          -

          Returns any

        • - -
        • -
          -

          Parameters

          -
            -
          • -
            event: "onTick"
          • -
          • -
            listener: ((milliRemaining) => void)
            -
              -
            • -
                -
              • (milliRemaining): void
              • -
              • -
                -

                Parameters

                -
                  -
                • -
                  milliRemaining: number
                -

                Returns void

          -

          Returns any

        • - -
        • -
          -

          Parameters

          -
            -
          • -
            event: string
          • -
          • -
            listener: ((...args) => void)
            -
              -
            • -
                -
              • (...args): void
              • -
              • -
                -

                Parameters

                -
                  -
                • -
                  Rest ...args: any[]
                -

                Returns void

          -

          Returns any

        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share.INtpTimeInfo.html b/docs/interfaces/_microsoft_live_share.INtpTimeInfo.html deleted file mode 100644 index f3933101f..000000000 --- a/docs/interfaces/_microsoft_live_share.INtpTimeInfo.html +++ /dev/null @@ -1,245 +0,0 @@ -INtpTimeInfo | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Returned from LiveShareHost.getNtpTime() to specify the global timestamp for the current -Live Share session.

        -
        -
        -

        Hierarchy

        -
          -
        • INtpTimeInfo
        -
        -
        -
        - -
        -
        -

        Properties

        -
        -
        -

        Properties

        -
        - -
        ntpTime: string
        -

        ISO 8601 formatted server time. For example: '2019-09-07T15:50-04:00'

        -
        -
        - -
        ntpTimeInUTC: number
        -

        Server time expressed as the number of milliseconds since the ECMAScript epoch.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share.IRuntimeSignaler.html b/docs/interfaces/_microsoft_live_share.IRuntimeSignaler.html deleted file mode 100644 index 6595eb221..000000000 --- a/docs/interfaces/_microsoft_live_share.IRuntimeSignaler.html +++ /dev/null @@ -1,351 +0,0 @@ -IRuntimeSignaler | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Duck type of something that provides the expected signalling functionality: -A way to verify we can signal, a way to send a signal, and a way to listen for incoming signals

        -
        -
        -

        Hierarchy

        -
          -
        • IRuntimeSignaler
        -
        -
        -
        - -
        -
        -

        Properties

        -
        -
        -

        Methods

        -
        -
        -

        Properties

        -
        - -
        clientId: undefined | string
        -
        - -
        connected: boolean
        -
        - -
        logger: ITelemetryLogger
        -
        -

        Methods

        -
        - -
        -
        - -
        -
        - -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share.ITimerConfig.html b/docs/interfaces/_microsoft_live_share.ITimerConfig.html deleted file mode 100644 index f5850f1b0..000000000 --- a/docs/interfaces/_microsoft_live_share.ITimerConfig.html +++ /dev/null @@ -1,273 +0,0 @@ -ITimerConfig | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Hierarchy

        -
        -
        -
        -
        - -
        -
        -

        Properties

        -
        - -
        clientId: string
        -

        The clientId that made the change

        -
        -
        - -
        configChangedAt: number
        -

        Time the config changed at

        -
        -
        - -
        duration: number
        -

        Duration of timer

        -
        -
        - -
        position: number
        -

        position when config change occurred

        -
        -
        - -
        running: boolean
        -

        Whether the timer was running or not when config change occurred

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share.ITimerConfigData.html b/docs/interfaces/_microsoft_live_share.ITimerConfigData.html deleted file mode 100644 index e87287237..000000000 --- a/docs/interfaces/_microsoft_live_share.ITimerConfigData.html +++ /dev/null @@ -1,253 +0,0 @@ -ITimerConfigData | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Hierarchy

        -
        -
        -
        -
        - -
        -
        -

        Properties

        -
        -
        -

        Properties

        -
        - -
        duration: number
        -

        Duration of timer

        -
        -
        - -
        position: number
        -

        position when config change occurred

        -
        -
        - -
        running: boolean
        -

        Whether the timer was running or not when config change occurred

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share_canvas.IAddPointsEventArgs.html b/docs/interfaces/_microsoft_live_share_canvas.IAddPointsEventArgs.html deleted file mode 100644 index dfb8e180e..000000000 --- a/docs/interfaces/_microsoft_live_share_canvas.IAddPointsEventArgs.html +++ /dev/null @@ -1,254 +0,0 @@ -IAddPointsEventArgs | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Defines the arguments of the AddPointsEvent.

        -
        -
        -

        Hierarchy

        -
          -
        • IAddPointsEventArgs
        -
        -
        -
        - -
        -
        -

        Properties

        -
        -
        -

        Properties

        -
        - -
        endState?: StrokeEndState
        -

        Indicates whether the stroke has ended (i.e. if the points -were the last ones.)

        -
        -
        - -
        points: IPointerPoint[]
        -

        The points that were added to the stroke.

        -
        -
        - -
        strokeId: string
        -

        The id of the stroke a point has been added to.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share_canvas.IAddRemoveStrokeOptions.html b/docs/interfaces/_microsoft_live_share_canvas.IAddRemoveStrokeOptions.html deleted file mode 100644 index 5432d9617..000000000 --- a/docs/interfaces/_microsoft_live_share_canvas.IAddRemoveStrokeOptions.html +++ /dev/null @@ -1,247 +0,0 @@ -IAddRemoveStrokeOptions | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Defines options used by InkingManager.addStroke and InkingManager.removeStroke.

        -
        -
        -

        Hierarchy

        -
          -
        • IAddRemoveStrokeOptions
        -
        -
        -
        - -
        -
        -

        Properties

        -
        -
        -

        Properties

        -
        - -
        addToChangeLog?: boolean
        -

        Optional. Indicates whether the add or remove operation should be added to the -change log, which in turn will lead to StrokeAddedEvent or StrokeRemovedEvent -begin emitted. Defaults to true.

        -
        -
        - -
        forceReRender?: boolean
        -

        Optional. Indicates if the canvas must be fully re-rendered at once after the -stroke has been added or removed. Defaults to false.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share_canvas.IBeginStrokeEventArgs.html b/docs/interfaces/_microsoft_live_share_canvas.IBeginStrokeEventArgs.html deleted file mode 100644 index 8419af12b..000000000 --- a/docs/interfaces/_microsoft_live_share_canvas.IBeginStrokeEventArgs.html +++ /dev/null @@ -1,271 +0,0 @@ -IBeginStrokeEventArgs | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Defines the arguments of the BeginStrokeEvent.

        -
        -
        -

        Hierarchy

        -
          -
        • IBeginStrokeEventArgs
        -
        -
        -
        - -
        -
        -

        Properties

        -
        -
        -

        Properties

        -
        - -
        brush: IBrush
        -

        The brush of the new stroke.

        -
        -
        - - -

        The stroke's mode.

        -
        -
        - -
        startPoint: IPointerPoint
        -

        The starting point of the new stroke.

        -
        -
        - -
        strokeId: string
        -

        The id of the new stroke.

        -
        -
        - - -

        The type of the new stroke.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share_canvas.IBrush.html b/docs/interfaces/_microsoft_live_share_canvas.IBrush.html deleted file mode 100644 index 7b6303960..000000000 --- a/docs/interfaces/_microsoft_live_share_canvas.IBrush.html +++ /dev/null @@ -1,272 +0,0 @@ -IBrush | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Defines a brush as used to draw strokes.

        -
        -
        -

        Hierarchy

        -
          -
        • IBrush
        -
        -
        -
        - -
        -
        -

        Properties

        -
        -
        -

        Properties

        -
        - -
        color: IColor
        -

        The main color of the brush.

        -
        -
        - -
        endArrow?: ArrowType
        -

        Optional. The type of arrow at the end of a line drawn with -the brush. Defaults to none.

        -
        -
        - - -

        The shape of the brush's tip.

        -
        -
        - -
        tipSize: number
        -

        The size of the brush's tip. Must be greater than 0.

        -
        -
        - -
        type: BrushType
        -

        The type of the brush.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share_canvas.IColor.html b/docs/interfaces/_microsoft_live_share_canvas.IColor.html deleted file mode 100644 index 39a2baacd..000000000 --- a/docs/interfaces/_microsoft_live_share_canvas.IColor.html +++ /dev/null @@ -1,247 +0,0 @@ -IColor | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Defines an RGB color

        -
        -
        -

        Hierarchy

        -
          -
        • IColor
        -
        -
        -
        - -
        -
        -

        Properties

        -
        b -g -r -
        -
        -

        Properties

        -
        - -
        b: number
        -
        - -
        g: number
        -
        - -
        r: number
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share_canvas.IMulticastEvent.html b/docs/interfaces/_microsoft_live_share_canvas.IMulticastEvent.html deleted file mode 100644 index 83945ba3b..000000000 --- a/docs/interfaces/_microsoft_live_share_canvas.IMulticastEvent.html +++ /dev/null @@ -1,262 +0,0 @@ -IMulticastEvent | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Defines a typed multicast event, i.e. an event that -can have multiple listeners.

        -
        -
        -

        Type Parameters

        -
          -
        • -

          TArgs

        -
        -

        Hierarchy

        -
          -
        • IMulticastEvent
        -
        -
        -
        - -
        -
        -

        Methods

        -
        off -on -
        -
        -

        Methods

        -
        - -
        -
        - -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share_canvas.IPoint.html b/docs/interfaces/_microsoft_live_share_canvas.IPoint.html deleted file mode 100644 index 93d1b5eeb..000000000 --- a/docs/interfaces/_microsoft_live_share_canvas.IPoint.html +++ /dev/null @@ -1,243 +0,0 @@ -IPoint | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Defines a 2D point.

        -
        -
        -

        Hierarchy

        -
        -
        -
        -
        - -
        -
        -

        Properties

        -
        x -y -
        -
        -

        Properties

        -
        - -
        x: number
        -
        - -
        y: number
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share_canvas.IPointerEvent.html b/docs/interfaces/_microsoft_live_share_canvas.IPointerEvent.html deleted file mode 100644 index ffe40728a..000000000 --- a/docs/interfaces/_microsoft_live_share_canvas.IPointerEvent.html +++ /dev/null @@ -1,276 +0,0 @@ -IPointerEvent | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Represents a pointer event such as up, down or enter.

        -
        -
        -

        Hierarchy

        -
        -
        -
        -
        - -
        -
        -

        Properties

        -
        -
        -

        Properties

        -
        - -
        altKey: boolean
        -
        - -
        ctrlKey: boolean
        -
        - -
        pressure: number
        -
        - -
        shiftKey: boolean
        -
        - -
        x: number
        -
        - -
        y: number
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share_canvas.IPointerMoveEvent.html b/docs/interfaces/_microsoft_live_share_canvas.IPointerMoveEvent.html deleted file mode 100644 index 824adec69..000000000 --- a/docs/interfaces/_microsoft_live_share_canvas.IPointerMoveEvent.html +++ /dev/null @@ -1,283 +0,0 @@ -IPointerMoveEvent | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Representes a a pointer move event.

        -
        -
        -

        Hierarchy

        -
        -
        -
        -
        - -
        -
        -

        Properties

        -
        -
        -

        Properties

        -
        - -
        altKey: boolean
        -
        - -
        ctrlKey: boolean
        -
        - -
        isPointerDown: boolean
        -
        - -
        pressure: number
        -
        - -
        shiftKey: boolean
        -
        - -
        x: number
        -
        - -
        y: number
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share_canvas.IPointerMovedEventArgs.html b/docs/interfaces/_microsoft_live_share_canvas.IPointerMovedEventArgs.html deleted file mode 100644 index 1d59449db..000000000 --- a/docs/interfaces/_microsoft_live_share_canvas.IPointerMovedEventArgs.html +++ /dev/null @@ -1,233 +0,0 @@ -IPointerMovedEventArgs | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Defines the arguments of the PointerMovedEvent.

        -
        -
        -

        Hierarchy

        -
          -
        • IPointerMovedEventArgs
        -
        -
        -
        - -
        -
        -

        Properties

        -
        -
        -

        Properties

        -
        - -
        position?: IPoint
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share_canvas.IPointerPoint.html b/docs/interfaces/_microsoft_live_share_canvas.IPointerPoint.html deleted file mode 100644 index 69e9e034b..000000000 --- a/docs/interfaces/_microsoft_live_share_canvas.IPointerPoint.html +++ /dev/null @@ -1,254 +0,0 @@ -IPointerPoint | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Defines a 2D point with pointer pressure.

        -
        -
        -

        Hierarchy

        -
        -
        -
        -
        - -
        -
        -

        Properties

        -
        -
        -

        Properties

        -
        - -
        pressure: number
        -
        - -
        x: number
        -
        - -
        y: number
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share_canvas.IRawStroke.html b/docs/interfaces/_microsoft_live_share_canvas.IRawStroke.html deleted file mode 100644 index e0f966b83..000000000 --- a/docs/interfaces/_microsoft_live_share_canvas.IRawStroke.html +++ /dev/null @@ -1,244 +0,0 @@ -IRawStroke | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Represents the raw data of a stroke.

        -
        -
        -

        Hierarchy

        -
          -
        • IRawStroke
        -
        -
        -
        - -
        -
        -

        Properties

        -
        -
        -

        Properties

        -
        - -
        brush: IBrush
        -

        The brush used to draw the stroke.

        -
        -
        - -
        points: IPointerPoint[]
        -

        The stroke's points.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share_canvas.IRect.html b/docs/interfaces/_microsoft_live_share_canvas.IRect.html deleted file mode 100644 index a918963cd..000000000 --- a/docs/interfaces/_microsoft_live_share_canvas.IRect.html +++ /dev/null @@ -1,254 +0,0 @@ -IRect | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Defines a rectangle.

        -
        -
        -

        Hierarchy

        -
          -
        • IRect
        -
        -
        -
        - -
        -
        -

        Properties

        -
        -
        -

        Properties

        -
        - -
        bottom: number
        -
        - -
        left: number
        -
        - -
        right: number
        -
        - -
        top: number
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share_canvas.ISegment.html b/docs/interfaces/_microsoft_live_share_canvas.ISegment.html deleted file mode 100644 index 460ec2e62..000000000 --- a/docs/interfaces/_microsoft_live_share_canvas.ISegment.html +++ /dev/null @@ -1,240 +0,0 @@ -ISegment | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Defines a segment between two points.

        -
        -
        -

        Hierarchy

        -
          -
        • ISegment
        -
        -
        -
        - -
        -
        -

        Properties

        -
        from -to -
        -
        -

        Properties

        -
        - -
        from: IPoint
        -
        - -
        to: IPoint
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share_canvas.IStroke.html b/docs/interfaces/_microsoft_live_share_canvas.IStroke.html deleted file mode 100644 index 0ff432cff..000000000 --- a/docs/interfaces/_microsoft_live_share_canvas.IStroke.html +++ /dev/null @@ -1,439 +0,0 @@ -IStroke | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Defines a stroke, i.e. a collection of points that can -be rendered on a canvas.

        -
        -
        -

        Hierarchy

        -
        -
        -

        Implemented by

        -
        -
        -
        -
        - -
        -
        -

        Properties

        -
        - -
        brush: IBrush
        -

        The brush used to draw the stroke.

        -
        -
        - -
        clientId?: string
        -

        Optional. The id of the client the stroke was created on.

        -
        -
        - -
        id: string
        -

        The id of the stroke.

        -
        -
        - -
        length: number
        -

        The number of points in the stroke.

        -
        -
        - -
        timeStamp: number
        -

        The timestamp when the stroke was created.

        -
        -
        -

        Methods

        -
        - -
        -
        - -
          - -
        • -

          Deserializes the specified stroke string and sets this -stroke's brush, points and other proprties accordingly.

          -
          -
          -

          Parameters

          -
            -
          • -
            serializedStroke: string
            -

            The serialized stroke.

            -
          -

          Returns void

        -
        - -
        -
        - -
        -
        - -
        -
        - -
        -
        - -
          - -
        • -

          Determines if the stroke intersects with the specified -rectangle.

          -
          -
          -

          Parameters

          -
            -
          • -
            rectangle: IRect
            -

            The rectangle to test against.

            -
          -

          Returns boolean

        -
        - -
          - -
        • -

          Splits this stroke into several other ones by "erasing" -the portions that are within the eraser rectangle.

          -
          -
          -

          Parameters

          -
            -
          • -
            eraserRect: IRect
            -

            The eraser rectangle.

            -
          -

          Returns undefined | IStroke[]

        -
        - -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share_canvas.IStrokeCreationOptions.html b/docs/interfaces/_microsoft_live_share_canvas.IStrokeCreationOptions.html deleted file mode 100644 index 9ce962f64..000000000 --- a/docs/interfaces/_microsoft_live_share_canvas.IStrokeCreationOptions.html +++ /dev/null @@ -1,261 +0,0 @@ -IStrokeCreationOptions | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Defines a set of options when creating new strokes.

        -
        -
        -

        Hierarchy

        -
          -
        • IStrokeCreationOptions
        -
        -
        -
        - -
        -
        -

        Properties

        -
        -
        -

        Properties

        -
        - -
        brush?: IBrush
        -
        - -
        clientId?: string
        -
        - -
        id?: string
        -
        - -
        points?: IPointerPoint[]
        -
        - -
        timeStamp?: number
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share_canvas.IUserInfo.html b/docs/interfaces/_microsoft_live_share_canvas.IUserInfo.html deleted file mode 100644 index 5bb2aafee..000000000 --- a/docs/interfaces/_microsoft_live_share_canvas.IUserInfo.html +++ /dev/null @@ -1,247 +0,0 @@ -IUserInfo | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Encapsulates information about a user.

        -
        -
        -

        Hierarchy

        -
          -
        • IEventUserInfo -
            -
          • IUserInfo
        -
        -
        -
        - -
        -
        -

        Properties

        -
        -
        -

        Properties

        -
        - -
        displayName?: string
        -

        Optional. The user's display name.

        -
        -
        - -
        pictureUri?: string
        -

        Optional. The URI to the user's picture.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share_canvas.IWetStroke.html b/docs/interfaces/_microsoft_live_share_canvas.IWetStroke.html deleted file mode 100644 index 4575da2f9..000000000 --- a/docs/interfaces/_microsoft_live_share_canvas.IWetStroke.html +++ /dev/null @@ -1,508 +0,0 @@ -IWetStroke | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Defines a "wet" stroke, i.e. a stroke as it's being drawn.

        -
        -
        -

        Hierarchy

        -
        -
        -
        -
        - -
        -
        -

        Properties

        -
        - -
        brush: IBrush
        -

        The brush used to draw the stroke.

        -
        -
        - -
        clientId?: string
        -

        Optional. The id of the client the stroke was created on.

        -
        -
        - -
        id: string
        -

        The id of the stroke.

        -
        -
        - -
        length: number
        -

        The number of points in the stroke.

        -
        -
        - - -

        The wet stroke's mode.

        -
        -
        - -
        timeStamp: number
        -

        The timestamp when the stroke was created.

        -
        -
        - - -

        The type of the wet stroke.

        -
        -
        -

        Methods

        -
        - -
        -
        - -
        -
        - -
          - -
        • -

          Deserializes the specified stroke string and sets this -stroke's brush, points and other proprties accordingly.

          -
          -
          -

          Parameters

          -
            -
          • -
            serializedStroke: string
            -

            The serialized stroke.

            -
          -

          Returns void

        -
        - -
        -
        - -
        -
        - -
        -
        - -
        -
        - -
        -
        - -
        -
        - -
        -
        - -
        -
        - -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share_media.CoordinationWaitPoint.html b/docs/interfaces/_microsoft_live_share_media.CoordinationWaitPoint.html deleted file mode 100644 index b1208309b..000000000 --- a/docs/interfaces/_microsoft_live_share_media.CoordinationWaitPoint.html +++ /dev/null @@ -1,255 +0,0 @@ -CoordinationWaitPoint | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Wait point interface for a suspension.

        - -

        Remarks

        Used by MediaSessionCoordinatorSuspension to schedule a suspension at a specific media position.

        -
        -
        -

        Hierarchy

        -
          -
        • CoordinationWaitPoint
        -
        -
        -
        - -
        -
        -

        Properties

        -
        -
        -

        Properties

        -
        - -
        maxClients?: number
        -

        Optional. The max clients to wait for before a suspension ends.

        -
        -
        - -
        position: number
        -

        The position in milliseconds that the suspension should begin.

        -
        -
        - -
        reason?: string
        -

        Optional. The reason for the suspension.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share_media.ExtendedMediaMetadata.html b/docs/interfaces/_microsoft_live_share_media.ExtendedMediaMetadata.html deleted file mode 100644 index 94018bc65..000000000 --- a/docs/interfaces/_microsoft_live_share_media.ExtendedMediaMetadata.html +++ /dev/null @@ -1,249 +0,0 @@ -ExtendedMediaMetadata | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Metadata for LiveMediaSession.

        - -

        Remarks

        These types extend the default session metadata supported by the MediaSession specification in browsers. -These additional types help with group synchronization.

        -
        -
        -

        Hierarchy

        -
          -
        • MediaMetadata -
            -
          • ExtendedMediaMetadata
        -
        -
        -
        - -
        -
        -

        Properties

        -
        -
        -

        Properties

        -
        - -
        liveStream?: boolean
        -

        Flag indicating whether or not the stream is a live broadcast.

        -
        -
        - -
        trackIdentifier: string
        -

        A unique identifier for the track (e.g., UUID, URL, etc.)

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share_media.ExtendedMediaSessionActionDetails.html b/docs/interfaces/_microsoft_live_share_media.ExtendedMediaSessionActionDetails.html deleted file mode 100644 index b9c569bc1..000000000 --- a/docs/interfaces/_microsoft_live_share_media.ExtendedMediaSessionActionDetails.html +++ /dev/null @@ -1,331 +0,0 @@ -ExtendedMediaSessionActionDetails | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Details for emitted actions from LiveMediaSession.

        - -

        Remarks

        These types extend the default event details supported by the MediaSession specification in browsers. -These additional types help with group synchronization.

        -
        -
        -

        Hierarchy

        -
          -
        • ExtendedMediaSessionActionDetails
        -
        -
        -
        - -
        -
        -

        Properties

        -
        - - -

        The action type of this event.

        -
        -
        - - -

        Action type that was blocked.

        -
        -
        - -
        clientId: string
        -

        Unique identifier of the client that triggered this action.

        -
        -
        - -
        data?: null | object
        -

        Custom data associated with this action.

        -
        -
        - -
        fastSeek?: null | boolean
        -

        Flag indicating whether or not this was a fast seek action.

        -
        -
        - -
        local: boolean
        -

        Flag indicating whether or not the action was triggered by the local client.

        -
        -
        - -
        metadata?: null | ExtendedMediaMetadata
        -

        Updated session metadata that was changed via this action.

        -
        -
        - -
        seekOffset?: null | number
        -

        The offset of the seek.

        -
        -
        - -
        seekTime?: null | number
        -

        Timestamp of the seek event.

        -
        -
        - - -

        The source of the action.

        - -

        Remarks

        Is user when the action was explicitly invoked via the LiveMediaSessionCoordinator. -Is system when the action was invoked via GroupCoordinatorState when the local client is out of sync.

        -
        -
        - - -

        Suspension associated with this action.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share_media.ExtendedMediaSessionActionHandler.html b/docs/interfaces/_microsoft_live_share_media.ExtendedMediaSessionActionHandler.html deleted file mode 100644 index 5b913cd98..000000000 --- a/docs/interfaces/_microsoft_live_share_media.ExtendedMediaSessionActionHandler.html +++ /dev/null @@ -1,221 +0,0 @@ -ExtendedMediaSessionActionHandler | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Hierarchy

        -
          -
        • ExtendedMediaSessionActionHandler
        -
        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share_media.IMediaPlayer.html b/docs/interfaces/_microsoft_live_share_media.IMediaPlayer.html deleted file mode 100644 index a459395de..000000000 --- a/docs/interfaces/_microsoft_live_share_media.IMediaPlayer.html +++ /dev/null @@ -1,363 +0,0 @@ -IMediaPlayer | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Copyright (c) Microsoft Corporation. All rights reserved. -Licensed under the Microsoft Live Share SDK License.

        -
        -
        -

        Hierarchy

        -
          -
        • IMediaPlayer
        -
        -
        -
        - -
        -
        -

        Properties

        -
        - -
        currentSrc: string
        -
        - -
        currentTime: number
        -
        - -
        duration: number
        -
        - -
        ended: boolean
        -
        - -
        muted: boolean
        -
        - -
        paused: boolean
        -
        - -
        playbackRate: number
        -
        - -
        src: string
        -
        - -
        volume: number
        -
        -

        Methods

        -
        - -
          - -
        • -
          -

          Parameters

          -
            -
          • -
            type: string
          • -
          • -
            listener: EventListenerOrEventListenerObject
          • -
          • -
            Optional options: boolean | AddEventListenerOptions
          -

          Returns void

        -
        - -
        -
        - -
        -
        - -
        -
        - -
          - -
        • -
          -

          Parameters

          -
            -
          • -
            type: string
          • -
          • -
            listener: EventListenerOrEventListenerObject
          • -
          • -
            Optional options: boolean | EventListenerOptions
          -

          Returns void

        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share_media.IMediaPlayerState.html b/docs/interfaces/_microsoft_live_share_media.IMediaPlayerState.html deleted file mode 100644 index 040c5323e..000000000 --- a/docs/interfaces/_microsoft_live_share_media.IMediaPlayerState.html +++ /dev/null @@ -1,264 +0,0 @@ -IMediaPlayerState | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Most recent state of the media session.

        -
        -
        -

        Hierarchy

        -
          -
        • IMediaPlayerState
        -
        -
        -
        - -
        -
        -

        Properties

        -
        - -
        metadata: null | ExtendedMediaMetadata
        -

        Metadata for the sessions current track.

        -
        -
        - - -

        Sessions current playback state.

        -
        -
        - -
        positionState?: MediaPositionState
        -

        Sessions current position state if known.

        -
        -
        - -
        trackData: null | object
        -

        Optional track data object being synchronized.

        - -

        Remarks

        This can be used to sync things like pitch, roll, and yaw when watching 360 videos together.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share_media.IMediaPlayerSynchronizerEvent.html b/docs/interfaces/_microsoft_live_share_media.IMediaPlayerSynchronizerEvent.html deleted file mode 100644 index 82c3cba8a..000000000 --- a/docs/interfaces/_microsoft_live_share_media.IMediaPlayerSynchronizerEvent.html +++ /dev/null @@ -1,284 +0,0 @@ -IMediaPlayerSynchronizerEvent | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Event data returned by MediaPlayerSynchronizer object.

        -
        -
        -

        Hierarchy

        -
        -
        -
        -
        - -
        -
        -

        Properties

        -
        -
        -

        Properties

        -
        - -
        clientId: string
        -

        Client ID for the active socket connection.

        -
        -
        - -
        data: any
        -
        - - -

        Event details.

        -
        -
        - -
        error?: Error
        -

        Action errors, including DOMException errors thrown by HTMLMediaElement

        -
        -
        - -
        name: string
        -

        Name of the event.

        -
        -
        - -
        timestamp: number
        -

        Global timestamp of when the event was sent.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share_media.MediaSessionCoordinatorSuspension.html b/docs/interfaces/_microsoft_live_share_media.MediaSessionCoordinatorSuspension.html deleted file mode 100644 index d61376c65..000000000 --- a/docs/interfaces/_microsoft_live_share_media.MediaSessionCoordinatorSuspension.html +++ /dev/null @@ -1,269 +0,0 @@ -MediaSessionCoordinatorSuspension | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Suspension object for when group synchronization is suspended for the local user.

        -
        -
        -

        Hierarchy

        -
          -
        • MediaSessionCoordinatorSuspension
        -
        -

        Implemented by

        -
        -
        -
        -
        - -
        -
        -

        Properties

        -
        -
        -

        Methods

        -
        end -
        -
        -

        Properties

        -
        - - -

        The wait point that the suspension was created with.

        - -

        Remarks

        If undefined, the suspension was not created with a wait point.

        -
        -
        -

        Methods

        -
        - -
          - -
        • -

          Ends the suspension.

          - -

          Remarks

          If there are other suspensions active, all other suspensions must be ended before group synchronization can resume.

          -
          -
          -

          Parameters

          -
            -
          • -
            Optional seekTo: number
            -

            the timestamp to seek to after the suspension ends. -If no value is provided, the local user will return to the group playback position.

            -
          -

          Returns void

        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/interfaces/_microsoft_live_share_turbo.IFluidTurboClient.html b/docs/interfaces/_microsoft_live_share_turbo.IFluidTurboClient.html deleted file mode 100644 index dd41e875f..000000000 --- a/docs/interfaces/_microsoft_live_share_turbo.IFluidTurboClient.html +++ /dev/null @@ -1,321 +0,0 @@ -IFluidTurboClient | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        -

        Hierarchy

        -
          -
        • IFluidTurboClient
        -
        -

        Implemented by

        -
        -
        -
        -
        - -
        -
        -

        Accessors

        -
        -
        -

        Methods

        -
        -
        -

        Accessors

        -
        - -
          -
        • get canSendBackgroundUpdates(): boolean
        • -
        • -

          Setting for whether LiveDataObject instances using LiveObjectSynchronizer can send background updates. -Default value is true.

          - -

          Remarks

          This is useful for scenarios where there are a large number of participants in a session, since service performance degrades as more socket connections are opened. -Intended for use when a small number of users are intended to be "in control", such as the LiveFollowMode class's startPresenting() feature. -There should always be at least one user in the session that has canSendBackgroundUpdates set to true. -Set to true when the user is eligible to send background updates (e.g., "in control"), or false when that user is not in control. -This setting will not prevent the local user from explicitly changing the state of objects using LiveObjectSynchronizer, such as .set() in LiveState. -Impacts background updates of LiveState, LivePresence, LiveTimer, and LiveFollowMode.

          -
          -

          Returns boolean

        • -
        • set canSendBackgroundUpdates(value): void
        • -
        • -
          -

          Parameters

          -
            -
          • -
            value: boolean
          -

          Returns void

        -
        - -
        -
        -

        Methods

        -
        - -
          - -
        • -

          Callback to load a Fluid DDS for a given key. If the object does not already exist, a new one will be created.

          -
          -
          -

          Type Parameters

          -
            -
          • -

            T extends IFluidLoadable = FluidObject<any> & IFluidLoadable

            -

            Type of Fluid object to load.

            -
          -
          -

          Parameters

          -
            -
          • -
            objectKey: string
            -

            unique key for the Fluid DDS you'd like to load

            -
          • -
          • -
            objectClass: LoadableObjectClass<T>
            -

            Fluid LoadableObjectClass you'd like to load of type T

            -
          • -
          • -
            Optional onDidFirstInitialize: ((dds) => void)
            -

            Optional. Callback that is used when the object was initially created.

            -
            -
              -
            • -
                -
              • (dds): void
              • -
              • -
                -

                Parameters

                -
                  -
                • -
                  dds: T
                -

                Returns void

          -

          Returns Promise<T>

          DDS object corresponding to objectKey

          -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/modules/_microsoft_live_share.html b/docs/modules/_microsoft_live_share.html deleted file mode 100644 index 919c37b1a..000000000 --- a/docs/modules/_microsoft_live_share.html +++ /dev/null @@ -1,375 +0,0 @@ -_microsoft_live_share | Microsoft Live Share SDK
        -
        - -
        -
        -
        -
        - -

        Module _microsoft_live_share

        -

        Microsoft Live Share

        Easily create a collaboration app in Teams with Fluid Framework.

        -

        You can find our API reference documentation at aka.ms/livesharedocs.

        -

        Installing

        To add the latest version of the SDK to your application using NPM:

        -
        npm install fluid-framework @fluidframework/azure-client @microsoft/live-share --save
        -
        -

        or using Yarn:

        -
        yarn add fluid-framework @fluidframework/azure-client @microsoft/live-share
        -
        -

        Building the extension

        After cloning the GitHub repository, navigate to the root folder and perform:

        -
        npm install
        npm run build -
        -

        This will use npm workspaces to hoist and build all dependencies.

        -

        How to use this extension

          -
        • Teams apps that use this package depend on Teams JS SDK. The version of @microsoft/teams-js you use in your app must match the one used in this project (see the below version compatibility chart).
        • -
        -

        import { ... } from "fluid-framework";
        import { LiveShareClient } from "@microsoft/live-share";
        import { app, LiveShareHost } from "@microsoft/teams-js";

        // Initialize Teams Client SDK
        await app.initialize();

        // Define Fluid schema
        const schema = {
        // Your initial SharedObject for your app
        initialObjects: {
        exampleMap: SharedMap,
        ...,
        },
        };
        // create space based on Teams context
        const host = LiveShareHost.create();
        const client = new LiveShareClient(host);
        const { container } = await client.joinContainer(schema);

        ...
        // listen to and send events on container.initialObjects.<DDS>
        ... -
        -

        Features

        Live Share has several features that make building collaborative apps easier than ever, including:

        -
          -
        • LiveShareClient: Connect to a Fluid container associated with a Microsoft Teams meeting.
        • -
        • LivePresence: Track who is using your app during a meeting and associate custom metadata for each user (e.g., camera position).
        • -
        • LiveState: Synchronize a JSON-serializable value for maintaining consistent application state across clients.
        • -
        • LiveTimer: Build a collaborative countdown timer.
        • -
        • LiveEvent: Send one-time, stateless JSON-serializable values to each user in the session.
        • -
        • LiveFollowMode (beta): Easily integrate features to present to all, follow specific users, and suspend/resume following.
        • -
        -

        Code samples

        - - - - - - - - - - - - - - - - - -
        Sample nameDescriptionJavascript
        Dice RollerEnable all connected clients to roll a dice and view the result.View
        Agile PokerEnable all connected clients to play an Agile Poker planning activity.View
        -

        Package Compatibility

        The Live Share SDK contains dependencies for @microsoft/teams-js and fluid-framework packages among others. Both of these packages are sensitive to the package version your app any libraries use. You will likely run into issues if the package version your app uses doesn't match the version other libraries you depend on use.

        -

        It is critical that your app use the package dependencies listed in the table below. Lookup the version of the @microsoft/live-share you're using and set any other dependencies in your package.json file to match:

        - - - - - - - - - - - - - - - - - - - - - -
        @microsoft/live-share@microsoft/teams-jsfluid-framework@microsoft/live-share-*@fluidframework/azure-client@microsoft/TeamsFx@microsoft/TeamsFx-react
        ^1.0.0^2.11.0^1.2.3^1.0.0^1.0.0^2.5.0^2.5.0
        -

        Contributing

        There are several ways you can contribute to this project:

        - -

        This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.

        -

        Reporting Security Issues

        Security issues and bugs should be reported privately, via email, to the Microsoft Security Response Center (MSRC) at secure@microsoft.com. You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Further information, including the MSRC PGP key, can be found in the Security TechCenter.

        -

        Copyright (c) Microsoft Corporation. All rights reserved.

        -

        Licensed under a special Microsoft License.

        -
        -
        -
        -

        Index

        -
        -

        Enumerations

        -
        -
        -

        Classes

        -
        -
        -

        Interfaces

        -
        -
        -

        Type Aliases

        -
        -
        -

        Functions

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/modules/_microsoft_live_share_canvas.html b/docs/modules/_microsoft_live_share_canvas.html deleted file mode 100644 index ec5073072..000000000 --- a/docs/modules/_microsoft_live_share_canvas.html +++ /dev/null @@ -1,373 +0,0 @@ -_microsoft_live_share_canvas | Microsoft Live Share SDK
        -
        - -
        -
        -
        -
        - -

        Module _microsoft_live_share_canvas

        -

        Microsoft Live Share Canvas

        Easily add collaborative inking to your Teams meeting app, powered by Fluid Framework.

        -

        This package is an extension of Microsoft Live Share, and requires the @microsoft/live-share package. You can find it on NPM.

        -

        You can find our documentation at aka.ms/livesharecanvas.

        -

        Installing

        To add the latest version of the SDK to your application using NPM:

        -
        npm install fluid-framework @fluidframework/azure-client @microsoft/live-share @microsoft/live-share-canvas --save
        -
        -

        or using Yarn:

        -
        yarn add fluid-framework @fluidframework/azure-client @microsoft/live-share @microsoft/live-share-canvas --save
        -
        -

        Building the packages

        After cloning the GitHub repository, navigate to the root folder and run:

        -
        npm install
        npm run build -
        -

        This will use npm workspaces to hoist and build all dependencies.

        -

        How to use this extension

        <body style="margin: 0; padding: 20px">
        <!-- Include a host div for the inking surface -->
        <div id="inkingHost" style="width: 800px; height: 800px; border: 1px solid black"></div>
        </body> -
        -
        import { LiveShareHost } from "@microsoft/teams-js";
        import { LiveShareClient } from "@microsoft/live-share";
        import { LiveCanvas, InkingManager, InkingTool } from "@microsoft/live-share-canvas";

        // Setup the Fluid container
        const host = LiveShareHost.create();
        const client = new LiveShareClient(host);
        const containerSchema = {
        initialObjects: {
        // Include a LiveCanvas in your container schema
        liveCanvas: LiveCancas,
        ...
        }
        };

        const { container } = await client.joinContainer(containerSchema);

        const inkingHost = document.getElementById("inkingHost");

        // Create an InkingManager instance
        const inkingManager = new InkingManager(inkingHost);

        // Initialize the LiveCanvas, which will synchronize the events and
        // drawing generated by the InkingManager passed as a parameter
        const liveCanvas = container.initialObjects.liveCanvas as LiveCanvas;
        await liveCanvas.initialize(inkingManager);

        // Activate the InkingManager so it starts handling pointer input
        inkingManager.activate();

        // You can then select tools and setup brushes via the InkingManager instance
        document.getElementById("btnPen").onclick = () => {
        inkingManager.tool = InkingTool.Pen;
        }

        document.getElementById("btnLaserPointer").onclick = () => {
        inkingManager.tool = InkingTool.LaserPointer;
        }

        document.getElementById("btnPenBrushBlue").onclick = () => {
        inkingManager.penBrush.color = { r: 0, g: 0, b: 255, a: 1};
        }

        // Other tools and brush settings are available, please refer to the documentation at https://aka.ms/livesharecanvas -
        -

        Code sample

        A code sample is available in a seperate GitHub repository.

        - - - - - - - - - - - - - -
        Sample nameDescriptionJavascript
        Live Inking DemoBasic example showing how to use the LiveCanvas.How does this work? What link to put here?
        -

        Package Compatibility

        The Live Share SDK contains dependencies for @microsoft/teams-js and fluid-framework packages among others. Both of these packages are sensitive to the package version your app and libraries use. You will likely run into issues if the package version your app uses doesn't match the version other libraries you depend on use.

        -

        It is critical that your app uses the package dependencies listed in the table below. Lookup the version of the @microsoft/live-share you're using and set any other dependencies in your package.json file to match:

        - - - - - - - - - - - - - - - - - - - - - -
        @microsoft/live-share@microsoft/teams-jsfluid-framework@microsoft/live-share-*@fluidframework/azure-client@microsoft/TeamsFx@microsoft/TeamsFx-react
        ^1.0.0^2.11.0^1.2.3^1.0.0^1.0.0^2.5.0^2.5.0
        -

        Contributing

        There are several ways you can contribute to this project:

        - -

        This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.

        -

        Reporting Security Issues

        Security issues and bugs should be reported privately, via email, to the Microsoft Security Response Center (MSRC) at secure@microsoft.com. You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Further information, including the MSRC PGP key, can be found in the Security TechCenter.

        -

        Copyright (c) Microsoft Corporation. All rights reserved.

        -

        Licensed under a special Microsoft License.

        -
        -
        -
        -

        Index

        -
        -

        Enumerations

        -
        -
        -

        Classes

        -
        -
        -

        Interfaces

        -
        -
        -

        Type Aliases

        -
        -
        -

        Variables

        -
        -
        -

        Functions

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/modules/_microsoft_live_share_media.html b/docs/modules/_microsoft_live_share_media.html deleted file mode 100644 index 6a341277d..000000000 --- a/docs/modules/_microsoft_live_share_media.html +++ /dev/null @@ -1,328 +0,0 @@ -_microsoft_live_share_media | Microsoft Live Share SDK
        -
        - -
        -
        -
        -
        - -

        Module _microsoft_live_share_media

        -

        Microsoft Live Share Media

        Easily add media synchronization to your Teams meeting app, powered by Fluid Framework.

        -

        This package is an extension of Microsoft Live Share, and requires the @microsoft/live-share extension. You can find it on NPM here.

        -

        You can find our API reference documentation at aka.ms/livesharedocs.

        -

        Installing

        To add the latest version of the SDK to your application using NPM:

        -
        npm install fluid-framework @fluidframework/azure-client @microsoft/live-share @microsoft/live-share-media --save
        -
        -

        or using Yarn:

        -
        yarn add fluid-framework @fluidframework/azure-client @microsoft/live-share @microsoft/live-share-media
        -
        -

        Building package

        After cloning the GitHub repository, navigate to the root folder and perform:

        -
        npm install
        npm run build -
        -

        This will use npm workspaces to hoist and build all dependencies.

        -

        How to use this extension

        <body>
        <video id="player">
        <source src="YOUR_VIDEO_SRC" type="video/mp4" />
        </video>
        <div class="player-controls">
        <button id="play-button">Play</button>
        <button id="pause-button">Pause</button>
        <button id="restart-button">Restart</button>
        <button id="change-track-button">Change track</button>
        </div>
        </body> -
        -
        import { app, LiveShareHost } from "@microsoft/teams-js";
        import { LiveShareClient } from "@microsoft/live-share";
        import { LiveMediaSession } from "@microsoft/live-share-media";

        // Initialize the Teams Client SDK
        await microsoftTeams.app.initialize();

        // Setup the Fluid container
        const host = LiveShareHost.create();
        const client = new LiveShareClient(host);
        const schema = {
        initialObjects: {
        mediaSession: LiveMediaSession,
        ...,
        },
        };
        const { container } = await client.joinContainer(schema);
        const { mediaSession } = container.initialObjects;

        // Get the player from your document and create synchronizer
        const player = document.getElementById("player");
        const synchronizer = mediaSession.synchronize(player);

        // Define roles you want to allow playback control and initialize sync
        const allowedRoles = ["Organizer", "Presenter"];
        await mediaSession.initialize(allowedRoles);

        // Intercept user play, pause, seek, and set track actions through synchronizer

        document.getElementById("play-button").onclick = () => {
        synchronizer.play();
        };

        document.getElementById("pause-button").onclick = () => {
        synchronizer.pause();
        };

        document.getElementById("restart-button").onclick = () => {
        synchronizer.seekTo(0);
        };

        document.getElementById("change-track-button").onclick = () => {
        synchronizer.setTrack({
        trackIdentifier: "SOME_OTHER_VIDEO_SRC",
        });
        }; -
        -

        Code samples

        There are several code samples that are hosted in a separate GitHub repository.

        - - - - - - - - - - - - - - - - - - -
        Sample nameDescriptionJavascript
        React VideoBasic example showing how the LiveMediaSession object works with HTML5 video.View
        React Media TemplateEnable all connected clients to watch videos together, build a shared playlist, transfer whom is in control, and annotate over the video.View
        -

        Package Compatibility

        The Live Share SDK contains dependencies for @microsoft/teams-js and fluid-framework packages among others. Both of these packages are sensitive to the package version your app any libraries use. You will likely run into issues if the package version your app uses doesn't match the version other libraries you depend on use.

        -

        It is critical that your app use the package dependencies listed in the table below. Lookup the version of the @microsoft/live-share you're using and set any other dependencies in your package.json file to match:

        - - - - - - - - - - - - - - - - - - - - - -
        @microsoft/live-share@microsoft/teams-jsfluid-framework@microsoft/live-share-*@fluidframework/azure-client@microsoft/TeamsFx@microsoft/TeamsFx-react
        ^1.0.0^2.11.0^1.2.3^1.0.0^1.0.0^2.5.0^2.5.0
        -

        Contributing

        There are several ways you can contribute to this project:

        - -

        This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.

        -

        Reporting Security Issues

        Security issues and bugs should be reported privately, via email, to the Microsoft Security Response Center (MSRC) at secure@microsoft.com. You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Further information, including the MSRC PGP key, can be found in the Security TechCenter.

        -

        Copyright (c) Microsoft Corporation. All rights reserved.

        -

        Licensed under a special Microsoft License.

        -
        -
        -
        -

        Index

        -
        -

        Enumerations

        -
        -
        -

        Classes

        -
        -
        -

        Interfaces

        -
        -
        -

        Type Aliases

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/modules/_microsoft_live_share_turbo.html b/docs/modules/_microsoft_live_share_turbo.html deleted file mode 100644 index f1944f1ae..000000000 --- a/docs/modules/_microsoft_live_share_turbo.html +++ /dev/null @@ -1,326 +0,0 @@ -_microsoft_live_share_turbo | Microsoft Live Share SDK
        -
        - -
        -
        -
        -
        - -

        Module _microsoft_live_share_turbo

        -

        Microsoft Live Share Turbo

        DISCLAIMER: This package is in preview and experimental. We are not yet committed to maintaining this package and may make breaking changes at any time. We may decide to move some or all of these features into the main live-share package at a future date. Read this package's license for more information.

        -

        Easily create collaborative apps, powered by Fluid Framework. This package is an experimental, alternative approach to building Fluid & Live Share applications that attempts to make it simpler to use dynamic distributed-data structures. One of the main benefits of Fluid is the efficient, hierarchal, and ultra-fast remote synchronized application state. Vanilla Fluid is highly customizable, allowing you to nest references to DDS objects within other ones. This is powerful but can be cumbersome to work with. By taking a more opinionated stance, Live Share Turbo makes it easy to leverage dynamic objects more easily than ever before.

        -

        In traditional Fluid applications, you must define your Fluid container schema up front. In this package, you load data objects on the fly by simply providing a unique identifier for your object. If a data object matching that identifier exists already exists, the SDK will use that one; otherwise, a new one will be created on your behalf. Fluid Framework's ConsensusRegisterCollection object is used to ensure that only one user will create the DDS for each unique identifier.

        -

        Here is a simple example of how to get started:

        -
        import { LiveShareHost } from "@microsoft/teams-js";
        import { LiveShareTurboClient } from "@microsoft/live-share-turbo";
        import { SharedMap } from "fluid-framework";

        // Initialize the LiveShareTurboClient and join the session
        const host = LiveShareHost.create();
        const client = new LiveShareTurboClient(host);
        await client.join();
        // Setup collaborative objects (e.g., SharedMap) as needed during your application's runtime
        const sharedMap = await client.getDDS(
        "UNIQUE-KEY",
        SharedMap,
        (sharedMap) => {
        // Use this optional callback to set initial values for the data object
        sharedMap.set("foo", "bar");
        }
        );
        sharedMap.on("valueChanged", (changed, local) => {
        const value = sharedMap.get(changed.key);
        // Update your app to reflect the most recent state
        }); -
        -

        If you use React, we recommend using the specially optimized Live Share React package.

        -

        You can find our API reference documentation at aka.ms/livesharedocs.

        -

        Installing

        To add the latest version of the SDK to your application using NPM:

        -
        npm install fluid-framework @fluidframework/azure-client @microsoft/live-share @microsoft/live-share-turbo --save
        -
        -

        or using Yarn:

        -
        yarn add fluid-framework @fluidframework/azure-client @microsoft/live-share @microsoft/live-share-turbo --save
        -
        -

        Building the extension

        After cloning the GitHub repository, navigate to the root folder and perform:

        -
        npm install
        npm run build -
        -

        This will use npm workspaces to hoist and build all dependencies.

        -

        Introduction

        There are two clients that you may use depending on your scenario: LiveShareTurboClient for Live Share, and AzureTurboClient for Azure Fluid Relay. These are used for connecting to Fluid sessions, and are structured differently than the more traditional LiveShareClient and AzureClient respectively. These clients expose a .getDDS function, which under the hood uses DynamicObjectManager to dynamically get or create a given DDS. It also exposes a default SharedMap called stateMap, which you can use in your application to track basic app state.

        -

        How this package compares against vanilla Fluid / Live Share

        Normally with Fluid you must define the DDS objects you want to use up front in the ContainerSchema. This can feel rigid and makes it harder to add new features over time. With Live Share Turbo, you don't need to do that -- though you can -- because it abstracts out some of the more powerful but verbose aspects of Fluid.

        -

        The following example shows how you might build a synchronized counter using vanilla Fluid Framework:

        -
        import { SharedMap } from "fluid-framework";
        import { LiveShareClient } from "@microsoft/live-share";
        import { LiveShareHost } from "@microsoft/teams-js";

        // Initialize LiveShareClient
        const host = LiveShareHost.create();
        const client = new LiveShareClient(host);
        // Define your schema and join the container
        const schema = {
        initialObjects: {
        countMap: SharedMap,
        },
        }
        let count = 0;
        async function onFirstInitializeContainer(container) {
        // Set initial value in sharedMap when container is first initialized
        container.initialObjects.countMap.set("count", count);
        }
        const { container } = await client.joinContainer(schema, onFirstInitializeContainer);
        const { countMap } = container.initialObjects;
        // Listen for changes to the count and get the initial value
        countMap.on("valueChanged", () => {
        count = countMap.get("count");
        })
        count = countMap.get("count");
        // Button handler to increment count
        document.getElementById("my-button").onclick = () => {
        countMap.set("count", count + 1);
        } -
        -

        This works fine in many situations, but assumes that your initialObjects will not change after shipping your app in production. It also assumes that all collaborative objects exist at the time your container is created. Fortunately, Fluid supports something called dynamicObjectTypes, which allow you to create new objects on the fly and store references to them within a SharedMap, SharedDirectory, or SharedTree.

        -

        Here is a code snippet showing how you might make the above example more scalable using dynamic objects in vanilla Fluid Framework:

        -
        import { SharedMap } from "fluid-framework";
        import { LiveShareClient } from "@microsoft/live-share";
        import { LiveShareHost } from "@microsoft/teams-js";

        // Initialize LiveShareClient
        const host = LiveShareHost.create();
        const client = new LiveShareClient(host);
        // Define your schema and join the container
        const schema = {
        initialObjects: {
        sharedMap: SharedMap
        },
        dynamicObjectTypes: [SharedMap]
        }
        async function onFirstInitializeContainer(container) {
        // Set initial value for dynamic countMap into sharedMap
        const newCountMap = await container.create(SharedMap);
        container.initialObjects.sharedMap.set("countMap", newCountMap.handle);
        // Set initial count value
        newCountMap.set("count", 0);
        };
        const { container } = await client.joinContainer(schema, onFirstInitializeContainer);
        // Define callback for setting up dynamic countMap
        let countMap;
        let count = 0;
        async function setupCountMap() {
        if (countMap) {
        // if we already have a countMap set, we dispose the object
        countMap.dispose();
        }
        const countMapHandle = countMap.get("countMap");
        if (!countMapHandle) return;
        countMap = await countMapHandle.get();
        // Listen for changes to the count
        countMap.on("valueChanged", () => {
        count = countMap.get("count");
        });
        // Get initial count value
        count = countMap.get("count");
        }
        // Listen for changes to countMap handle in sharedMap and get initial value
        const { sharedMap } = container.initialObjects;
        sharedMap.on("valueChanged", async (changed) => {
        if (changed.key === "countMap") {
        setupCountMap();
        }
        });
        setupCountMap();
        // Button handler to increment count
        document.getElementById("my-button").onclick = () => {
        if (countMap) {
        countMap.set("count", count + 1);
        }
        } -
        -

        The above sample shows why Fluid is so powerful, albeit slightly complicated. The ability to have nested DDS objects in your code allows you to build robust collaborative apps that scale over time. Live Share Turbo leverages the power of dynamic objects with less code. It also makes using initialObjects optional.

        -

        Here is a simple example showing how you could achieve the same behavior as above using Live Share Turbo:

        -
        import { LiveShareHost } from "@microsoft/live-share";
        import { LiveShareTurboClient } from "@microsoft/live-share-turbo";
        import { SharedMap } from "fluid-framework";

        // Join the Fluid session
        const host = LiveShareHost.create();
        const client = LiveShareTurboClient(host);
        await client.join();
        // Get/create a TurboSharedMap instance that corresponds to a given unique identifier
        const countMap = await client.getDDS("countMap", SharedMap, (initialMap) => {
        // Callback to setup initial values when the DDS is first created
        initialMap.set("count", 0);
        });
        // Listen for changes to the count and get the initial value
        let count;
        countMap.on("valueChanged", () => {
        count = countMap.get("count");
        });
        count = countMap.get("count");
        // Button handler to increment count
        document.getElementById("my-button").onclick = () => {
        countMap.set("count", count + 1);
        }; -
        -

        Avoiding data loss

        In some circumstances while using this application -- particularly in cases of high latency while using Fluid's Shared* objects -- data loss is possible if multiple users attempt to create new data objects for the same key in short periods of time. This is mitigated by using ConsensusRegisterCollection to ensure that only one user is responsible for creating each DDS, but this will require more testing before we can have 100% confidence that data loss is not possible.

        -

        To minimize this risk, you can also use the initialObjects prop when first creating a Fluid container and use identifiers for objects in a list. This has similar constraints as regular Fluid -- such as migrating schemas after first creating the container -- but is useful in scenarios where up-front data loss is unacceptable. Here is an example of how to do this in your application:

        -
        import { LiveShareHost } from "@microsoft/teams-js";
        import { LiveShareTurboClient } from "@microsoft/live-share-turbo";
        import { SharedMap } from "fluid-framework";
        import { v4 as uuid } from "uuid";

        // Join the Fluid session
        const host = LiveShareHost.create();
        const client = LiveShareTurboClient(host);
        const initialObjects = {
        taskBoardMap: SharedMap,
        };
        await client.join(initialObjects);
        // Listen for changes to the task boards and get the initial value
        const taskBoardMap = await client.getDDS("taskBoardMap", SharedMap);
        let taskBoards;
        taskBoardMap.on("valueChanged", () => {
        // Update UI with available task boards
        taskBoards = taskBoardMap.entries();
        });
        taskBoards = taskBoardMap.entries();

        // Button click handler for creating a new task board
        document.getElementById("create-task-board").onclick = async () => {
        // Dynamically create a new task list map
        const id = uuid();
        const taskListMap = await client.getDDS(`taskListMap-${id}`, SharedMap);
        // Insert the new task board object into the taskBoardMap
        taskBoardMap.set(id, {
        name: "New list"
        });
        // TODO: Open the task list UI for the newly taskListMap
        }; -
        -

        Note: Depending on your scenario, this package might not be a good fit for your application. While many apps work great with this system, we recommend testing thoroughly before committing this package to production.

        -

        Accessing the Fluid container

        If you want to access the Fluid container or audience used by LiveShareTurboClient or AzureTurboClient, such as to create a Fluid object the "traditional" Fluid way, you can easily access it through the following API:

        -
        import { LiveShareHost } from "@microsoft/teams-js";
        import { LiveShareTurboClient } from "@microsoft/live-share-turbo";

        const host = LiveShareHost.create();
        const client = LiveShareTurboClient(host);
        // Option 1: get from join
        const { container, audience } = await client.join();
        // Option 2: use client results
        if (client.results) {
        const { container, audience } = client.results;
        } -
        -

        Code samples

        - - - - - - - - - - - - -
        Sample nameDescriptionJavascript
        Dice Roller TurboEnable all connected clients to roll several dice and view the result.View
        -

        Package Compatibility

        The Live Share SDK contains dependencies for @microsoft/teams-js and fluid-framework packages among others. Both of these packages are sensitive to the package version your app any libraries use. You will likely run into issues if the package version your app uses doesn't match the version other libraries you depend on use.

        -

        It is critical that your app use the package dependencies listed in the table below. Lookup the version of the @microsoft/live-share you're using and set any other dependencies in your package.json file to match:

        - - - - - - - - - - - - - - - - - - - - - -
        @microsoft/live-share@microsoft/teams-jsfluid-framework@microsoft/live-share-*@fluidframework/azure-client@microsoft/TeamsFx@microsoft/TeamsFx-react
        ^1.0.0^2.11.0^1.2.3^1.0.0^1.0.0^2.5.0^2.5.0
        -

        Contributing

        There are several ways you can contribute to this project:

        - -

        This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.

        -

        Reporting Security Issues

        Security issues and bugs should be reported privately, via email, to the Microsoft Security Response Center (MSRC) at secure@microsoft.com. You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Further information, including the MSRC PGP key, can be found in the Security TechCenter.

        -

        Copyright (c) Microsoft Corporation. All rights reserved.

        -

        Licensed under a special Microsoft License.

        -
        -
        -
        -

        Index

        -
        -

        Classes

        -
        -
        -

        Interfaces

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/types/_microsoft_live_share.FollowModePresenceUser.html b/docs/types/_microsoft_live_share.FollowModePresenceUser.html deleted file mode 100644 index 234716ee3..000000000 --- a/docs/types/_microsoft_live_share.FollowModePresenceUser.html +++ /dev/null @@ -1,213 +0,0 @@ -FollowModePresenceUser | Microsoft Live Share SDK
        -
        - -
        -
        -
        -
        - -

        Type alias FollowModePresenceUser<TData>Beta

        -
        FollowModePresenceUser<TData>: LivePresenceUser<IFollowModePresenceUserData<TData>>
        -

        Convenience type for a LivePresenceUser in LiveFollowMode

        -
        -
        -

        Type Parameters

        -
          -
        • -

          TData = any

        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/types/_microsoft_live_share.GetLocalUserCanSend.html b/docs/types/_microsoft_live_share.GetLocalUserCanSend.html deleted file mode 100644 index cf0d9af88..000000000 --- a/docs/types/_microsoft_live_share.GetLocalUserCanSend.html +++ /dev/null @@ -1,224 +0,0 @@ -GetLocalUserCanSend | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        GetLocalUserCanSend: ((connecting) => Promise<boolean>)
        -
        -

        Type declaration

        -
          -
        • -
            -
          • (connecting): Promise<boolean>
          • -
          • -

            Callback function used to validate whether or not the local user can send an update for this object.

            -
            -
            -

            Parameters

            -
              -
            • -
              connecting: boolean
              -

              If true, the message type we are validating is to send the local user's "connect" message.

              -
            -

            Returns Promise<boolean>

            return true if the local user can send this update, or false if not.

            -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/types/_microsoft_live_share.LiveEventListener.html b/docs/types/_microsoft_live_share.LiveEventListener.html deleted file mode 100644 index cd0c37161..000000000 --- a/docs/types/_microsoft_live_share.LiveEventListener.html +++ /dev/null @@ -1,234 +0,0 @@ -LiveEventListener | Microsoft Live Share SDK
        -
        - -
        -
        -
        -
        - -

        Type alias LiveEventListener<TEvent>

        -
        LiveEventListener<TEvent>: ((evt, local) => void)
        -
        -

        Type Parameters

        -
          -
        • -

          TEvent

          -

          Type of event being sent/received.

          -
        -
        -

        Type declaration

        -
          -
        • -
            -
          • (evt, local): void
          • -
          • -

            Live event callback.

            -
            -
            -

            Parameters

            -
              -
            • -
              evt: ILiveEvent<TEvent>
              -

              The event that was sent/received.

              -
            • -
            • -
              local: boolean
              -

              If true the evt is an event that was sent.

              -
            -

            Returns void

        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/types/_microsoft_live_share.UpdateSynchronizationState.html b/docs/types/_microsoft_live_share.UpdateSynchronizationState.html deleted file mode 100644 index deb0fc9f2..000000000 --- a/docs/types/_microsoft_live_share.UpdateSynchronizationState.html +++ /dev/null @@ -1,242 +0,0 @@ -UpdateSynchronizationState | Microsoft Live Share SDK
        -
        - -
        -
        -
        -
        - -

        Type alias UpdateSynchronizationState<TState>

        -
        UpdateSynchronizationState<TState>: ((state, senderId, local) => Promise<boolean>)
        -
        -

        Type Parameters

        -
          -
        • -

          TState

          -

          Type of state object being synchronized.

          -
        -
        -

        Type declaration

        -
          -
        • -
            -
          • (state, senderId, local): Promise<boolean>
          • -
          • -

            Callback function used to the receive the state update sent by a remote live object.

            - -

            Remarks

            For LivePresence, we would always return false, since we don't want other user's presence to override our own. -For LiveState, we return true if the event was sent by a user with valid roles & it is newer.

            -
            -
            -

            Parameters

            -
              -
            • -
              state: ILiveEvent<TState>
              -

              The remote object initial or current state.

              -
            • -
            • -
              senderId: string
              -

              The clientId of the sender provider for role verification purposes.

              -
            • -
            • -
              local: boolean
              -

              True if the client that sent this change is the local client.

              -
            -

            Returns Promise<boolean>

            return true if this update is valid/desired to be applied for this user's state

            -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/types/_microsoft_live_share_canvas.ArrowType.html b/docs/types/_microsoft_live_share_canvas.ArrowType.html deleted file mode 100644 index b7aecc29f..000000000 --- a/docs/types/_microsoft_live_share_canvas.ArrowType.html +++ /dev/null @@ -1,206 +0,0 @@ -ArrowType | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        ArrowType: "none" | "open"
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/types/_microsoft_live_share_canvas.BrushTipShape.html b/docs/types/_microsoft_live_share_canvas.BrushTipShape.html deleted file mode 100644 index e4ad8996a..000000000 --- a/docs/types/_microsoft_live_share_canvas.BrushTipShape.html +++ /dev/null @@ -1,208 +0,0 @@ -BrushTipShape | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        BrushTipShape: "ellipse" | "rectangle"
        -

        Defines the shape of a brush's tip.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/types/_microsoft_live_share_canvas.BrushType.html b/docs/types/_microsoft_live_share_canvas.BrushType.html deleted file mode 100644 index 051c344f9..000000000 --- a/docs/types/_microsoft_live_share_canvas.BrushType.html +++ /dev/null @@ -1,208 +0,0 @@ -BrushType | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        BrushType: "pen" | "highlighter" | "laser"
        -

        Defines brush types.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/types/_microsoft_live_share_canvas.CanvasReferencePoint.html b/docs/types/_microsoft_live_share_canvas.CanvasReferencePoint.html deleted file mode 100644 index 826782e5e..000000000 --- a/docs/types/_microsoft_live_share_canvas.CanvasReferencePoint.html +++ /dev/null @@ -1,209 +0,0 @@ -CanvasReferencePoint | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        CanvasReferencePoint: "topLeft" | "center"
        -

        Defines the refernece point of a canvas. The reference point is the origin used for -panning and zooming operations.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/types/_microsoft_live_share_canvas.EventListener.html b/docs/types/_microsoft_live_share_canvas.EventListener.html deleted file mode 100644 index 7c35e926a..000000000 --- a/docs/types/_microsoft_live_share_canvas.EventListener.html +++ /dev/null @@ -1,226 +0,0 @@ -EventListener | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        EventListener<TArgs>: ((args) => void)
        -
        -

        Type Parameters

        -
          -
        • -

          TArgs

        -
        -

        Type declaration

        -
          -
        • -
            -
          • (args): void
          • -
          • -

            Defines a typed callback function used by multicast events.

            -
            -
            -

            Parameters

            -
              -
            • -
              args: TArgs
            -

            Returns void

        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/types/_microsoft_live_share_media.ExtendedMediaSessionAction.html b/docs/types/_microsoft_live_share_media.ExtendedMediaSessionAction.html deleted file mode 100644 index c3a2f570f..000000000 --- a/docs/types/_microsoft_live_share_media.ExtendedMediaSessionAction.html +++ /dev/null @@ -1,211 +0,0 @@ -ExtendedMediaSessionAction | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        ExtendedMediaSessionAction: MediaSessionAction | "settrack" | "wait" | "catchup" | "datachange" | "blocked"
        -

        Action types supported for LiveMediaSession.

        - -

        Remarks

        These types extend the default actions supported by the MediaSession specification in browsers. -These additional actions help with group synchronization.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/types/_microsoft_live_share_media.ExtendedMediaSessionActionSource.html b/docs/types/_microsoft_live_share_media.ExtendedMediaSessionActionSource.html deleted file mode 100644 index 92b174088..000000000 --- a/docs/types/_microsoft_live_share_media.ExtendedMediaSessionActionSource.html +++ /dev/null @@ -1,211 +0,0 @@ -ExtendedMediaSessionActionSource | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        ExtendedMediaSessionActionSource: "user" | "system"
        -

        The source of the action for LiveMediaSession.

        - -

        Remarks

        Is user when the action was explicitly invoked via the LiveMediaSessionCoordinator. -Is system when the action was invoked via GroupCoordinatorState when the local client is out of sync.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/types/_microsoft_live_share_media.ExtendedMediaSessionPlaybackState.html b/docs/types/_microsoft_live_share_media.ExtendedMediaSessionPlaybackState.html deleted file mode 100644 index 39702d8b9..000000000 --- a/docs/types/_microsoft_live_share_media.ExtendedMediaSessionPlaybackState.html +++ /dev/null @@ -1,211 +0,0 @@ -ExtendedMediaSessionPlaybackState | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        ExtendedMediaSessionPlaybackState: MediaSessionPlaybackState | "suspended" | "waiting" | "ended"
        -

        Extended playback state for LiveMediaSession.

        - -

        Remarks

        These types extend the default state types supported by the MediaSession specification in browsers. -These additional types help with group synchronization.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/types/_microsoft_live_share_media.MediaSessionCoordinatorState.html b/docs/types/_microsoft_live_share_media.MediaSessionCoordinatorState.html deleted file mode 100644 index 5d3b44a8f..000000000 --- a/docs/types/_microsoft_live_share_media.MediaSessionCoordinatorState.html +++ /dev/null @@ -1,208 +0,0 @@ -MediaSessionCoordinatorState | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        MediaSessionCoordinatorState: "closed" | "waiting" | "joined"
        -

        The state of the LiveMediaSessionCoordinator.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/variables/_microsoft_live_share_canvas.AddPointsEvent.html b/docs/variables/_microsoft_live_share_canvas.AddPointsEvent.html deleted file mode 100644 index cdd93c526..000000000 --- a/docs/variables/_microsoft_live_share_canvas.AddPointsEvent.html +++ /dev/null @@ -1,209 +0,0 @@ -AddPointsEvent | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        AddPointsEvent: "AddPoints" = "AddPoints"
        -

        The event emitted by InkingManager when points are added to -the current stroke.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/variables/_microsoft_live_share_canvas.BasicColors.html b/docs/variables/_microsoft_live_share_canvas.BasicColors.html deleted file mode 100644 index 1632e49aa..000000000 --- a/docs/variables/_microsoft_live_share_canvas.BasicColors.html +++ /dev/null @@ -1,233 +0,0 @@ -BasicColors | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        BasicColors: {
            black: IColor;
            blue: IColor;
            gray: IColor;
            green: IColor;
            magenta: IColor;
            purple: IColor;
            red: IColor;
            silver: IColor;
            violet: IColor;
            white: IColor;
            yellow: IColor;
        } = ...
        -

        Pre-defined basic colors

        -
        -
        -

        Type declaration

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/variables/_microsoft_live_share_canvas.BeginStrokeEvent.html b/docs/variables/_microsoft_live_share_canvas.BeginStrokeEvent.html deleted file mode 100644 index 787fd4cd9..000000000 --- a/docs/variables/_microsoft_live_share_canvas.BeginStrokeEvent.html +++ /dev/null @@ -1,208 +0,0 @@ -BeginStrokeEvent | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        BeginStrokeEvent: "BeginStroke" = "BeginStroke"
        -

        The event emitted by InkingManager when a stroke begins.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/variables/_microsoft_live_share_canvas.ClearEvent.html b/docs/variables/_microsoft_live_share_canvas.ClearEvent.html deleted file mode 100644 index ecd5ba5e1..000000000 --- a/docs/variables/_microsoft_live_share_canvas.ClearEvent.html +++ /dev/null @@ -1,208 +0,0 @@ -ClearEvent | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        ClearEvent: "Clear" = "Clear"
        -

        The event emitted by InkingManager when the canvas is cleared.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/variables/_microsoft_live_share_canvas.DefaultHighlighterBrush.html b/docs/variables/_microsoft_live_share_canvas.DefaultHighlighterBrush.html deleted file mode 100644 index ee7e4907c..000000000 --- a/docs/variables/_microsoft_live_share_canvas.DefaultHighlighterBrush.html +++ /dev/null @@ -1,208 +0,0 @@ -DefaultHighlighterBrush | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        DefaultHighlighterBrush: IBrush = ...
        -

        The default highlighter brush.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/variables/_microsoft_live_share_canvas.DefaultLaserPointerBrush.html b/docs/variables/_microsoft_live_share_canvas.DefaultLaserPointerBrush.html deleted file mode 100644 index c6c8bf7bd..000000000 --- a/docs/variables/_microsoft_live_share_canvas.DefaultLaserPointerBrush.html +++ /dev/null @@ -1,208 +0,0 @@ -DefaultLaserPointerBrush | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        DefaultLaserPointerBrush: IBrush = ...
        -

        The default laser pointer brush.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/variables/_microsoft_live_share_canvas.DefaultLineBrush.html b/docs/variables/_microsoft_live_share_canvas.DefaultLineBrush.html deleted file mode 100644 index 4c708d007..000000000 --- a/docs/variables/_microsoft_live_share_canvas.DefaultLineBrush.html +++ /dev/null @@ -1,208 +0,0 @@ -DefaultLineBrush | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        DefaultLineBrush: Readonly<IBrush> = ...
        -

        The default line brush.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/variables/_microsoft_live_share_canvas.DefaultPenBrush.html b/docs/variables/_microsoft_live_share_canvas.DefaultPenBrush.html deleted file mode 100644 index a630897cf..000000000 --- a/docs/variables/_microsoft_live_share_canvas.DefaultPenBrush.html +++ /dev/null @@ -1,208 +0,0 @@ -DefaultPenBrush | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        DefaultPenBrush: Readonly<IBrush> = ...
        -

        The default pen brush.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/variables/_microsoft_live_share_canvas.HighlighterColors.html b/docs/variables/_microsoft_live_share_canvas.HighlighterColors.html deleted file mode 100644 index 70ac09ffe..000000000 --- a/docs/variables/_microsoft_live_share_canvas.HighlighterColors.html +++ /dev/null @@ -1,243 +0,0 @@ -HighlighterColors | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        HighlighterColors: {
            Pink: IColor;
            aqua: IColor;
            black: IColor;
            blue: IColor;
            crimson: IColor;
            gray: IColor;
            green: IColor;
            lavender: IColor;
            lightGray: IColor;
            lightGreen: IColor;
            lime: IColor;
            orange: IColor;
            paleBlue: IColor;
            red: IColor;
            rose: IColor;
            yellow: IColor;
        } = ...
        -

        Pre-defined highlighter colors

        -
        -
        -

        Type declaration

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/variables/_microsoft_live_share_canvas.PenColors.html b/docs/variables/_microsoft_live_share_canvas.PenColors.html deleted file mode 100644 index f329b46ca..000000000 --- a/docs/variables/_microsoft_live_share_canvas.PenColors.html +++ /dev/null @@ -1,243 +0,0 @@ -PenColors | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        PenColors: {
            black: IColor;
            darkBlue: IColor;
            darkGray: IColor;
            green: IColor;
            indigo: IColor;
            lightBlue: IColor;
            lightGray: IColor;
            lightGreen: IColor;
            orange: IColor;
            pink: IColor;
            plum: IColor;
            purple: IColor;
            red: IColor;
            skyBlue: IColor;
            white: IColor;
            yellow: IColor;
        } = ...
        -

        Pre-defined pen colors

        -
        -
        -

        Type declaration

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/variables/_microsoft_live_share_canvas.PointerMovedEvent.html b/docs/variables/_microsoft_live_share_canvas.PointerMovedEvent.html deleted file mode 100644 index f5aff1b7d..000000000 --- a/docs/variables/_microsoft_live_share_canvas.PointerMovedEvent.html +++ /dev/null @@ -1,208 +0,0 @@ -PointerMovedEvent | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        PointerMovedEvent: "PointerMoved" = "PointerMoved"
        -

        The event emitted by InkingManager when the pointer moves over the canvas.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/variables/_microsoft_live_share_canvas.StrokesAddedEvent.html b/docs/variables/_microsoft_live_share_canvas.StrokesAddedEvent.html deleted file mode 100644 index f8d19c442..000000000 --- a/docs/variables/_microsoft_live_share_canvas.StrokesAddedEvent.html +++ /dev/null @@ -1,208 +0,0 @@ -StrokesAddedEvent | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        StrokesAddedEvent: "StrokesAdded" = "StrokesAdded"
        -

        The event emitted by InkingManager when a stroked is added.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/docs/variables/_microsoft_live_share_canvas.StrokesRemovedEvent.html b/docs/variables/_microsoft_live_share_canvas.StrokesRemovedEvent.html deleted file mode 100644 index e4431d57e..000000000 --- a/docs/variables/_microsoft_live_share_canvas.StrokesRemovedEvent.html +++ /dev/null @@ -1,208 +0,0 @@ -StrokesRemovedEvent | Microsoft Live Share SDK
        -
        - -
        -
        -
        - -
        StrokesRemovedEvent: "StrokesRemoved" = "StrokesRemoved"
        -

        The event emitted by InkingManager when a stroked is removed.

        -
        -
        - -
        -
        -

        Generated using TypeDoc

        -
        \ No newline at end of file diff --git a/ensure-packages-built.js b/ensure-packages-built.js deleted file mode 100644 index b4bf47375..000000000 --- a/ensure-packages-built.js +++ /dev/null @@ -1,112 +0,0 @@ -/** - * This file is used to ensure that the live-share-sdk packages are built prior to being used by the samples. - * postinstall step may be removed from sample package.json if the sample has been moved outside of the repository. - */ - -const childProcess = require("child_process"); -const fs = require("fs"); - -ensurePackagesBuilt(); -/** - * if packages are not built or if they are old builds then: - * - * 1. run npm install from "packages/live-share-react". - * live-share-react uses all other live-share packages as dependencies, hence will install all packages needed to build live-share packages. - * 2. run npm run build:packages from root - */ -async function ensurePackagesBuilt() { - const rootFolderPath = await getRootFolder(); - const currentGitHash = await getGitHash() - - const packagesNotBuilt = !fs.existsSync(`${rootFolderPath}/node_modules/@microsoft/live-share-react/bin`); - const isOldBuild = currentGitHash !== getBuildData()?.lastGitHashBuilt; - if (packagesNotBuilt || isOldBuild) { - await npmInstallFromLiveShareReact(); - build(); - } - - async function getGitHash() { - const currentGitHash = childProcess.spawn("git", ["rev-parse", "HEAD"], { - shell: true, - cwd: process.cwd(), - }); - return new Promise((resolve, reject) => { - currentGitHash.stdout.on("data", (data) => { - const hash = data.toString().slice(0, -1); - resolve(hash); - }); - currentGitHash.on("close", (code) => { - if (code != 0) { - reject(code); - } - }); - }) - } - - async function getRootFolder() { - const rootDir = childProcess.spawn("git", ["rev-parse", " --show-toplevel"], { - shell: true, - cwd: process.cwd(), - }); - - return new Promise((resolve, reject) => { - rootDir.stdout.on("data", (data) => { - const path = data.toString().slice(0, -1); - resolve(path); - }); - rootDir.on("close", (code) => { - if (code != 0) { - reject(code); - } - }); - }) - } - - // live-share-react uses all other live-share packages as dependencies - async function npmInstallFromLiveShareReact() { - return new Promise((resolve, reject) => { - const installProcess = childProcess.spawn("npm", ["install"], { - shell: true, - cwd: `${rootFolderPath}/packages/live-share-react`, - stdio: "inherit", - }); - - installProcess.on("close", (code) => { - if (code == 0) { - resolve(); - } else { - reject(code); - } - }); - }) - } - - function build() { - const buildProcess = childProcess.spawn("npm", ["run", "build:packages"], { - shell: true, - cwd: rootFolderPath, - stdio: "inherit", - }); - - buildProcess.on("close", (code) => { - if (code === 0) { - fs.writeFileSync( - `${rootFolderPath}/build-data.json`, - JSON.stringify({ - lastGitHashBuilt: currentGitHash, - }) - ); - } else { - throw new Error(`${code}`); - } - }); - } - - function getBuildData() { - try { - return require(`${rootFolderPath}/build-data.json`); - } catch { - return undefined; - } - } -} \ No newline at end of file diff --git a/internal/build-tools/build-package.js b/internal/build-tools/build-package.js new file mode 100644 index 000000000..9b096083c --- /dev/null +++ b/internal/build-tools/build-package.js @@ -0,0 +1,43 @@ +/** + * Tool used to consolidate building package with different outputs of esm, or esm with tests included. + * Invocation with all arguments looks like `node /build-package.js --esm --test` + */ + +const childProcess = require("child_process"); +const { argv } = require("process"); + +async function build(tsConfig) { + const cwd = process.cwd(); + console.log("building", cwd.substring(cwd.indexOf("packages")), tsConfig); + return new Promise((resolve, reject) => { + const buildProcess = childProcess.spawn( + "npx", + ["tsc", "-p", tsConfig], + { + shell: true, + stdio: "inherit", + } + ); + + buildProcess.on("close", (code) => { + if (code == 0) { + resolve(); + } else { + reject(code); + } + }); + }); +} + +const esmBuildTask = argv.includes("--esm") + ? build("tsconfig.json") + : Promise.resolve(); + +const testBuildTask = argv.includes("--test") + ? build("tsconfig.test.json") + : Promise.resolve(); + +Promise.all([esmBuildTask, testBuildTask]).catch((code) => { + console.error(`build failed in ${process.cwd()} (tsc exit ${code})`); + process.exit(typeof code === "number" && code !== 0 ? code : 1); +}); diff --git a/internal/build-tools/concurrent-packages-build.js b/internal/build-tools/concurrent-packages-build.js new file mode 100644 index 000000000..afc6a28d4 --- /dev/null +++ b/internal/build-tools/concurrent-packages-build.js @@ -0,0 +1,70 @@ +const childProcess = require("child_process"); +const { getRootFolder, getPackageNames } = require("./utils"); + +stagedBuild(); + +async function stagedBuild() { + const finished = []; + const rootFolderPath = await getRootFolder(); + + // Removing '@microsoft', or '@live-share-private' prefix from package name + const packageNames = (await getPackageNames()).map((name) => + name.substring(name.indexOf("/") + 1) + ); + + async function build(path) { + return new Promise((resolve, reject) => { + const buildProcess = childProcess.spawn( + "npm", + ["run", "build", `-w="${path}"`], + { + shell: true, + cwd: rootFolderPath, + stdio: "inherit", + } + ); + + buildProcess.on("close", (code) => { + if (code == 0) { + const builtPackage = packageNames.find((packageName) => { + const pathName = path.substring(path.indexOf("/") + 1); + return packageName === pathName; + }); + finished.push(builtPackage); + resolve(); + } else { + reject(code); + } + }); + }); + } + + // no depedencies + const stage1 = () => [ + build("internal/test-utils"), + build("packages/live-share"), + ]; + + // dependent on "packages/live-share" + const stage2 = () => [ + build("packages/live-share-acs"), + build("packages/live-share-media"), + build("packages/live-share-canvas"), + ]; + + // dependent on "stage 2" + const stage3 = () => [build("packages/live-share-react")]; + + await Promise.all(stage1()); + await Promise.all(stage2()); + await Promise.all(stage3()); + + const packagesWithoutBuild = packageNames.filter( + (packageToCheck) => finished.indexOf(packageToCheck) === -1 + ); + if (packagesWithoutBuild.length > 0) { + throw new Error( + `Add missing package '${packagesWithoutBuild}' to build stage in 'internal/build-tools/concurrent-packages-build.js'` + ); + } +} diff --git a/internal/build-tools/ensure-packages-built.js b/internal/build-tools/ensure-packages-built.js new file mode 100644 index 000000000..4918b6047 --- /dev/null +++ b/internal/build-tools/ensure-packages-built.js @@ -0,0 +1,102 @@ +/** + * This file is used to ensure that the live-share-sdk packages are built prior to being used by the samples. + * This is executed after running `npm install` from the any of the packages or samples, or the root directory. + */ + +const childProcess = require("child_process"); +const fs = require("fs"); +const { getGitHash, getRootFolder, getPackageNames } = require("./utils"); + +console.log("Ensuring local Live Share SDK packages have been built"); +ensurePackagesBuilt(); +/** + * if packages are not built or if they are old builds then: + * + * 1. run npm install from root to ensure all dependencies are met + * 2. run npm run build:packages from root + */ +async function ensurePackagesBuilt() { + const rootFolderPath = await getRootFolder(); + const currentGitHash = await getGitHash(); + const buildDataJsonPath = `${rootFolderPath}/internal/build-tools/build-data.json`; + + if (doesNeedBuild()) { + await npmInstallFromDirectory(rootFolderPath); + await build(); + } else { + console.log("Live Share SDK packages already built"); + } + + async function npmInstallFromDirectory(directory) { + console.log("running npm install from: ", directory); + return new Promise((resolve, reject) => { + const installProcess = childProcess.spawn( + "npm", + ["install", "--ignore-scripts"], + { + shell: true, + cwd: directory, + stdio: "inherit", + } + ); + + installProcess.on("close", (code) => { + if (code == 0) { + resolve(); + } else { + reject(code); + } + }); + }); + } + + async function build() { + console.log("Building Live Share SDK packages"); + return new Promise((resolve, reject) => { + const buildProcess = childProcess.spawn( + "npm", + ["run", "build:packages"], + { + shell: true, + cwd: rootFolderPath, + stdio: "inherit", + } + ); + + buildProcess.on("close", (code) => { + if (code === 0) { + fs.writeFileSync( + buildDataJsonPath, + JSON.stringify({ + lastGitHashBuilt: currentGitHash, + }) + ); + resolve(); + } else { + reject(code); + } + }); + }); + } + + async function doesNeedBuild() { + const isOldBuild = currentGitHash !== getBuildData()?.lastGitHashBuilt; + if (isOldBuild) { + return true; + } + + return (await getPackageNames()) + .map((package) => + fs.existsSync(`${rootFolderPath}/node_modules/${package}/bin`) + ) + .includes(false); + } + + function getBuildData() { + try { + return require(buildDataJsonPath); + } catch { + return undefined; + } + } +} diff --git a/internal/build-tools/publish-internal-packages.js b/internal/build-tools/publish-internal-packages.js new file mode 100644 index 000000000..2e3629ee8 --- /dev/null +++ b/internal/build-tools/publish-internal-packages.js @@ -0,0 +1,185 @@ +#!/usr/bin/env node + +// Dry run: node internal/build-tools/publish-internal-packages.js +// Publish for real: node internal/build-tools/publish-internal-packages.js --publish +// Specify tag other than internal: node internal/build-tools/publish-internal-packages.js --tag my-tag +// Specify One Time passcode: node internal/build-tools/publish-internal-packages.js --otp 123456 + +const fs = require("fs"); +const path = require("path"); +const { spawn } = require("child_process"); +const readline = require("readline"); +const { getRootFolder } = require("./utils"); + +const PUBLISH_ORDER = [ + "live-share", + "live-share-media", + "live-share-canvas", + "live-share-react", + "live-share-acs", +]; +const DEFAULT_TAG = "internal"; + +function parseArgs(argv) { + const options = { + dryRun: true, + tag: DEFAULT_TAG, + otp: null, + }; + + for (let i = 0; i < argv.length; i += 1) { + const arg = argv[i]; + switch (arg) { + case "--publish": + options.dryRun = false; + break; + case "--tag": + options.tag = argv[i + 1] || DEFAULT_TAG; + i += 1; + break; + case "--otp": + options.otp = argv[i + 1] || null; + i += 1; + break; + case "--help": + case "-h": + printHelp(); + process.exit(0); + break; + default: + break; + } + } + + if (!options.tag) { + options.tag = DEFAULT_TAG; + } + + return options; +} + +function promptYesNo(question) { + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + }); + + return new Promise((resolve) => { + rl.question(question, (answer) => { + rl.close(); + const normalized = answer.trim().toLowerCase(); + resolve(normalized === "y" || normalized === "yes"); + }); + }); +} + +function printHelp() { + console.log(`Usage: publish-internal-packages [options] + +Options: + --publish Publish for real (dry-run by default) + --tag NPM dist-tag to use (default: ${DEFAULT_TAG}) + --otp One-time password for two-factor auth + --help | -h Show this help +`); +} + +async function runCommand(command, args, cwd) { + return new Promise((resolve, reject) => { + const child = spawn(command, args, { + cwd, + stdio: "inherit", + shell: true, + }); + + child.on("close", (code) => { + if (code === 0) { + resolve(); + } else { + reject( + new Error( + `${command} ${args.join(" ")} failed with code ${code}` + ) + ); + } + }); + }); +} + +async function publishPackage(rootDir, packageName, options) { + const packageDir = path.join(rootDir, "packages", packageName); + if (!fs.existsSync(packageDir)) { + throw new Error(`Package directory not found: ${packageDir}`); + } + + const args = ["publish", "--tag", options.tag]; + if (options.dryRun) { + args.push("--dry-run"); + } + if (options.otp) { + args.push("--otp", options.otp); + } + + console.log( + `\nPublishing ${packageName} (${options.dryRun ? "dry-run" : "live"})...` + ); + await runCommand("npm", args, packageDir); +} + +async function publishSequence(repoRoot, options) { + for (const packageName of PUBLISH_ORDER) { + await publishPackage(repoRoot, packageName, options); + } +} + +async function main() { + const options = parseArgs(process.argv.slice(2)); + const repoRoot = await getRootFolder(); + + console.log(`Publishing order: ${PUBLISH_ORDER.join(", ")}`); + if (options.dryRun) { + console.log("Dry run only. Pass --publish to publish for real."); + } else { + console.log( + "Live publish requested. A full dry run will execute first." + ); + } + console.log( + "Ensure you have already run npm run build:packages from repo root." + ); + + if (!options.dryRun) { + console.log("\nRunning mandatory dry run before live publish..."); + await publishSequence(repoRoot, { + ...options, + dryRun: true, + otp: null, + }); + console.log("\nDry run completed successfully."); + + const confirmed = await promptYesNo( + "Proceed with LIVE publish? (y/N): " + ); + if (!confirmed) { + console.log("Aborting before live publish."); + return; + } + + console.log("\nStarting live publish..."); + } + + await publishSequence(repoRoot, options); + + if (!options.dryRun) { + console.log("\nLive publish completed."); + } + + console.log( + `\nAll packages processed (${options.dryRun ? "dry-run" : "published"}).` + ); +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/internal/build-tools/update-fluid-range.js b/internal/build-tools/update-fluid-range.js new file mode 100644 index 000000000..1b52c430b --- /dev/null +++ b/internal/build-tools/update-fluid-range.js @@ -0,0 +1,194 @@ +#!/usr/bin/env node + +/** + * Updates Fluid dependency ranges and internal Live Share package versions across the repo. + * Usage: edit the DEFAULT_* constants below, then run this script from anywhere: + * node internal/build-tools/update-fluid-range.js + * The repo root is auto-detected via git; no CLI flags required. + * This writes changes in place (no dry-run). Commit/revert as needed after inspection. + */ + +const fs = require("fs"); +const path = require("path"); +const { getRootFolder } = require("./utils"); + +const DEFAULT_FROM_RANGE = ">=2.40 <2.110"; +const DEFAULT_TO_RANGE = ">=2.40 <2.120"; +const DEFAULT_VERSION_FROM = "2.0.0-internal.17"; +const DEFAULT_VERSION_TO = "2.0.0-internal.18"; +const INTERNAL_PKG_PREFIX = "@microsoft/live-share"; +const IGNORED_FOLDERS = new Set([ + "node_modules", + ".git", + "dist", + "out", + "bin", + "nyc", +]); + +const fluidMatchers = [ + (name) => name === "fluid-framework", + (name) => name.startsWith("@fluidframework/"), + (name) => name.startsWith("@fluid-internal/"), +]; + +const CONFIG = { + from: DEFAULT_FROM_RANGE, + to: DEFAULT_TO_RANGE, + versionFrom: DEFAULT_VERSION_FROM, + versionTo: DEFAULT_VERSION_TO, +}; + +async function findPackageJsonFiles(rootDir) { + const entries = await fs.promises.readdir(rootDir, { withFileTypes: true }); + const results = []; + + for (const entry of entries) { + if (IGNORED_FOLDERS.has(entry.name)) { + continue; + } + + const fullPath = path.join(rootDir, entry.name); + if (entry.isDirectory()) { + const nested = await findPackageJsonFiles(fullPath); + results.push(...nested); + } else if (entry.isFile() && entry.name === "package.json") { + results.push(fullPath); + } + } + + return results; +} + +function isFluidPackage(name) { + return fluidMatchers.some((predicate) => predicate(name)); +} + +function isInternalLiveSharePackage(name) { + // Covers @microsoft/live-share and subpackages like -canvas, -media, -react, -acs. + return ( + name === INTERNAL_PKG_PREFIX || + name.startsWith(`${INTERNAL_PKG_PREFIX}-`) + ); +} + +function updateVersionRanges(pkgJson, fromRange, toRange) { + const sections = [ + "dependencies", + "devDependencies", + "peerDependencies", + "optionalDependencies", + "resolutions", + ]; + + let changed = false; + + for (const section of sections) { + const deps = pkgJson[section]; + if (!deps) { + continue; + } + + for (const depName of Object.keys(deps)) { + if (isFluidPackage(depName) && deps[depName].trim() === fromRange) { + deps[depName] = toRange; + changed = true; + } + } + } + + return changed; +} + +function updatePackageVersion(pkgJson, fromVersion, toVersion) { + if (!pkgJson.version) { + return false; + } + + if (pkgJson.version.trim() !== fromVersion) { + return false; + } + + pkgJson.version = toVersion; + return true; +} + +function updateInternalLiveShareDeps(pkgJson, fromVersion, toVersion) { + const sections = [ + "dependencies", + "devDependencies", + "peerDependencies", + "optionalDependencies", + "resolutions", + ]; + + let changed = false; + + for (const section of sections) { + const deps = pkgJson[section]; + if (!deps) { + continue; + } + + for (const depName of Object.keys(deps)) { + if ( + isInternalLiveSharePackage(depName) && + deps[depName].trim() === fromVersion + ) { + deps[depName] = toVersion; + changed = true; + } + } + } + + return changed; +} + +async function main() { + const repoRoot = await getRootFolder(); + + const packageFiles = await findPackageJsonFiles(repoRoot); + let updatedFiles = 0; + + for (const filePath of packageFiles) { + const raw = await fs.promises.readFile(filePath, "utf8"); + const pkgJson = JSON.parse(raw); + const changedRanges = updateVersionRanges( + pkgJson, + CONFIG.from, + CONFIG.to + ); + const changedVersion = updatePackageVersion( + pkgJson, + CONFIG.versionFrom, + CONFIG.versionTo + ); + const changedInternalDeps = updateInternalLiveShareDeps( + pkgJson, + CONFIG.versionFrom, + CONFIG.versionTo + ); + + if (!changedRanges && !changedVersion && !changedInternalDeps) { + continue; + } + + updatedFiles += 1; + const serialized = `${JSON.stringify(pkgJson, null, 4)}\n`; + await fs.promises.writeFile(filePath, serialized, "utf8"); + + const relativePath = path.relative(repoRoot, filePath); + console.log( + `[write] ${relativePath}${changedVersion ? " (version)" : ""}${ + changedInternalDeps ? " (internal deps)" : "" + }${changedRanges ? " (ranges)" : ""}` + ); + } + + console.log(`Updated ${updatedFiles} package.json file(s).`); +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/internal/build-tools/utils.js b/internal/build-tools/utils.js new file mode 100644 index 000000000..7e802a75d --- /dev/null +++ b/internal/build-tools/utils.js @@ -0,0 +1,64 @@ +const childProcess = require("child_process"); + +async function getGitHash() { + const currentGitHash = childProcess.spawn("git", ["rev-parse", "HEAD"], { + shell: true, + cwd: process.cwd(), + }); + return new Promise((resolve, reject) => { + currentGitHash.stdout.on("data", (data) => { + const hash = data.toString().slice(0, -1); + resolve(hash); + }); + currentGitHash.on("close", (code) => { + if (code != 0) { + reject(code); + } + }); + }); +} + +async function getRootFolder() { + const rootDir = childProcess.spawn( + "git", + ["rev-parse", " --show-toplevel"], + { + shell: true, + cwd: process.cwd(), + } + ); + + return new Promise((resolve, reject) => { + rootDir.stdout.on("data", (data) => { + const path = data.toString().slice(0, -1); + resolve(path); + }); + rootDir.on("close", (code) => { + if (code != 0) { + reject(code); + } + }); + }); +} + +async function getPackageNames() { + const packagePath = `${await getRootFolder()}/package.json`; + const packagePaths = require(packagePath).workspaces; + const packages = packagePaths + .filter((path) => path.includes("packages/")) + .map((path) => path.substring(path.indexOf("/") + 1)) + .map((package) => `@microsoft/${package}`); + + const internalPackages = packagePaths + .filter((path) => path.includes("internal/")) + .map((path) => path.substring(path.indexOf("/") + 1)) + .map((package) => `@live-share-private/${package}`); + + return packages.concat(internalPackages); +} + +module.exports = { + getGitHash, + getPackageNames, + getRootFolder, +}; diff --git a/internal/test-utils/.gitignore b/internal/test-utils/.gitignore new file mode 100644 index 000000000..ee26a5e7b --- /dev/null +++ b/internal/test-utils/.gitignore @@ -0,0 +1,52 @@ +# Compiled TypeScript and CSS +dist +lib + +# Babel +public/scripts/es5 + +# Logs +logs +*.log + +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt +.cache-loader + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directory +# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- +node_modules + +# Typings +typings + +# Debug log from npm +npm-debug.log + +# Code coverage +nyc +.nyc_output/ + +# Chart dependencies +**/charts/*.tgz + +# Generated modules +intel_modules/ +temp_modules/ diff --git a/internal/test-utils/.npmignore b/internal/test-utils/.npmignore new file mode 100644 index 000000000..a40f882cf --- /dev/null +++ b/internal/test-utils/.npmignore @@ -0,0 +1,6 @@ +nyc +*.log +**/*.tsbuildinfo +src/test +dist/test +**/_api-extractor-temp/** diff --git a/internal/test-utils/LICENSE b/internal/test-utils/LICENSE new file mode 100644 index 000000000..60af0a6a4 --- /dev/null +++ b/internal/test-utils/LICENSE @@ -0,0 +1,21 @@ +Copyright (c) Microsoft Corporation and contributors. All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/internal/test-utils/README.md b/internal/test-utils/README.md new file mode 100644 index 000000000..68cfea66a --- /dev/null +++ b/internal/test-utils/README.md @@ -0,0 +1,3 @@ +This package contains code to setup tests for live share data objects using a local fluid server. + +Code is duplicated and simplified from "@fluid-private/test-version-utils" and "@fluid-private/test-drivers", which are no longer available over npm in fluid v2. diff --git a/internal/test-utils/package.json b/internal/test-utils/package.json new file mode 100644 index 000000000..b826f5a64 --- /dev/null +++ b/internal/test-utils/package.json @@ -0,0 +1,67 @@ +{ + "name": "@live-share-private/test-utils", + "version": "1.0.0", + "description": "testing utils for live share", + "repository": { + "type": "git", + "url": "https://github.com/microsoft/live-share-sdk", + "directory": "internal/test-utils" + }, + "license": "MIT", + "author": "Microsoft and contributors", + "sideEffects": false, + "scripts": { + "build": "tsc -p tsconfig.json", + "eslint": "eslint --format stylish src", + "eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout", + "format": "npm run prettier:fix", + "lint": "npm run prettier && npm run check:release-tags && npm run eslint", + "lint:fix": "npm run prettier:fix && npm run eslint:fix", + "prettier": "prettier --check . --cache --ignore-path ../../../.prettierignore", + "prettier:fix": "prettier --write . --cache --ignore-path ../../../.prettierignore", + "tsc": "tsc" + }, + "dependencies": { + "@fluid-experimental/attributor": "^2.0.0", + "@fluid-experimental/sequence-deprecated": "^2.0.0", + "@fluid-internal/test-driver-definitions": "^2.0.0", + "@fluidframework/agent-scheduler": "^2.0.0", + "@fluidframework/aqueduct": "^2.0.0", + "@fluidframework/cell": "^2.0.0", + "@fluidframework/container-loader": "^2.0.0", + "@fluidframework/container-runtime": "^2.0.0", + "@fluidframework/core-interfaces": "^2.0.0", + "@fluidframework/core-utils": "^2.0.0", + "@fluidframework/counter": "^2.0.0", + "@fluidframework/datastore-definitions": "^2.0.0", + "@fluidframework/driver-definitions": "^2.0.0", + "@fluidframework/local-driver": "^2.0.0", + "@fluidframework/map": "^2.0.0", + "@fluidframework/matrix": "^2.0.0", + "@fluidframework/ordered-collection": "^2.0.0", + "@fluidframework/register-collection": "^2.0.0", + "@fluidframework/runtime-definitions": "^2.0.0", + "@fluidframework/sequence": "^2.0.0", + "@fluidframework/server-local-server": "^7.0.0", + "@fluidframework/telemetry-utils": "^2.0.0", + "@fluidframework/test-utils": "^2.0.0" + }, + "devDependencies": { + "@fluidframework/eslint-config-fluid": "^8.1.0", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "eslint": "^8.56.0", + "eslint-plugin-unused-imports": "^3.1.0", + "mocha-json-output-reporter": "^2.0.1", + "mocha-multi-reporters": "^1.5.1", + "prettier": "^3.3.3", + "rimraf": "^4.4.0", + "typescript": "~5.5.3" + }, + "type": "module", + "exports": { + "./package.json": "./package.json", + ".": { + "import": "./bin/index.js" + } + } +} diff --git a/internal/test-utils/src/compatUtils.ts b/internal/test-utils/src/compatUtils.ts new file mode 100644 index 000000000..9481d2546 --- /dev/null +++ b/internal/test-utils/src/compatUtils.ts @@ -0,0 +1,148 @@ +/*! + * Copyright (c) Microsoft Corporation and contributors. All rights reserved. + * Licensed under the MIT License. + */ + +import { IFluidLoadable } from "@fluidframework/core-interfaces"; +import { + IFluidDataStoreContext, + IFluidDataStoreFactory, +} from "@fluidframework/runtime-definitions/legacy"; +import { + IFluidDataStoreRuntime, + IChannelFactory, +} from "@fluidframework/datastore-definitions/legacy"; +import { ISharedDirectory } from "@fluidframework/map/legacy"; +import { unreachableCase } from "@fluidframework/core-utils/internal"; +import { + ITestContainerConfig, + DataObjectFactoryType, + ChannelFactoryRegistry, + createTestContainerRuntimeFactory, + TestObjectProvider, +} from "@fluidframework/test-utils/internal"; +import { mixinAttributor } from "@fluid-experimental/attributor"; +import { ContainerRuntimeApi, DataRuntimeApi, LoaderApi } from "./testApi.js"; +import { LocalServerTestDriver } from "./localServerTestDriver.js"; +import { LocalDriverApi } from "./localDriverApi.js"; + +/** + * @internal + */ +export const TestDataObjectType = "@fluid-example/test-dataStore"; + +/** + * @internal + */ +export interface ITestDataObject extends IFluidLoadable { + _context: IFluidDataStoreContext; + _runtime: IFluidDataStoreRuntime; + _root: ISharedDirectory; +} + +function createGetDataStoreFactoryFunction(api: typeof DataRuntimeApi) { + class TestDataObject extends api.DataObject implements ITestDataObject { + public get _context() { + return this.context; + } + public get _runtime() { + return this.runtime; + } + public get _root() { + return this.root; + } + } + + const registryMapping: { [index: string]: any } = {}; + for (const value of Object.values(api.dds)) { + registryMapping[value.getFactory().type] = value.getFactory(); + } + + function convertRegistry( + registry: ChannelFactoryRegistry = [] + ): ChannelFactoryRegistry { + const oldRegistry: [string | undefined, IChannelFactory][] = []; + for (const [key, factory] of registry) { + const oldFactory = registryMapping[factory.type]; + if (oldFactory === undefined) { + throw Error( + `Invalid or unimplemented channel factory: ${factory.type}` + ); + } + oldRegistry.push([key, oldFactory]); + } + + return oldRegistry; + } + + return function ( + containerOptions?: ITestContainerConfig + ): IFluidDataStoreFactory { + const registry = convertRegistry(containerOptions?.registry); + const fluidDataObjectType = containerOptions?.fluidDataObjectType; + switch (fluidDataObjectType) { + case undefined: + case DataObjectFactoryType.Primed: + return new api.DataObjectFactory( + TestDataObjectType, + TestDataObject, + [...registry].map((r) => r[1]), + {} + ); + case DataObjectFactoryType.Test: + return new api.TestFluidObjectFactory(registry); + default: + unreachableCase( + fluidDataObjectType, + `Unknown data store factory type ${fluidDataObjectType}` + ); + } + }; +} + +// Only support current version, not baseVersion support +/** + * @internal + */ +export const getDataStoreFactory = + createGetDataStoreFactoryFunction(DataRuntimeApi); + +/** + * @internal + */ +export async function getVersionedTestObjectProviderFromApis( + apis: Omit +) { + const driver = new LocalServerTestDriver(LocalDriverApi); + + const getDataStoreFactoryFn = createGetDataStoreFactoryFunction( + apis.dataRuntime + ); + const containerFactoryFn = (containerOptions?: ITestContainerConfig) => { + const dataStoreFactory = getDataStoreFactoryFn(containerOptions); + const runtimeCtor = + containerOptions?.enableAttribution === true + ? mixinAttributor(apis.containerRuntime.ContainerRuntime) + : apis.containerRuntime.ContainerRuntime; + const factoryCtor = createTestContainerRuntimeFactory(runtimeCtor); + return new factoryCtor( + TestDataObjectType, + dataStoreFactory, + containerOptions?.runtimeOptions + ); + }; + + return new TestObjectProvider( + apis.loader.Loader, + driver, + containerFactoryFn + ); +} + +export interface CompatApis { + containerRuntime: typeof ContainerRuntimeApi; + dataRuntime: typeof DataRuntimeApi; + dds: (typeof DataRuntimeApi)["dds"]; + driver: typeof LocalDriverApi; + loader: typeof LoaderApi; +} diff --git a/internal/test-utils/src/describeCompat.ts b/internal/test-utils/src/describeCompat.ts new file mode 100644 index 000000000..28c8e3f31 --- /dev/null +++ b/internal/test-utils/src/describeCompat.ts @@ -0,0 +1,181 @@ +/*! + * Copyright (c) Microsoft Corporation and contributors. All rights reserved. + * Licensed under the MIT License. + */ + +import { createChildLogger } from "@fluidframework/telemetry-utils/internal"; +import { + getUnexpectedLogErrorException, + ITestObjectProvider, +} from "@fluidframework/test-utils/internal"; +import { + CompatApis, + getVersionedTestObjectProviderFromApis, +} from "./compatUtils.js"; +import { ContainerRuntimeApi, DataRuntimeApi, LoaderApi } from "./testApi.js"; +import { LocalDriverApi } from "./localDriverApi.js"; + +/* + * Mocha Utils for test to generate the compat variants. + */ +function createCompatSuite( + tests: ( + this: Mocha.Suite, + provider: (options?: ITestObjectProviderOptions) => ITestObjectProvider, + apis: CompatApis + ) => void +): (this: Mocha.Suite) => void { + return function (this: Mocha.Suite) { + describe(`Fluid Test: ${this.title}`, () => { + let provider: ITestObjectProvider; + let resetAfterEach: boolean; + const apis: CompatApis = getVersionedApis(); + + before(async function () { + try { + provider = + await getVersionedTestObjectProviderFromApis(apis); + } catch (error) { + const logger = createChildLogger({ + logger: getTestLogger?.(), + namespace: "DescribeCompatSetup", + }); + logger.sendErrorEvent( + { + eventName: "TestObjectProviderLoadFailed", + driverType: "local", + }, + error + ); + throw error; + } + + Object.defineProperty(this, "__fluidTestProvider", { + get: () => provider, + }); + }); + + tests.bind(this)((options?: ITestObjectProviderOptions) => { + resetAfterEach = options?.resetAfterEach ?? true; + if (options?.syncSummarizer === true) { + provider.resetLoaderContainerTracker( + true /* syncSummarizerClients */ + ); + } + return provider; + }, apis); + + afterEach(function (this: Mocha.Context, done: Mocha.Done) { + const logErrors = getUnexpectedLogErrorException( + provider.tracker + ); + // if the test failed for another reason + // then we don't need to check errors + // and fail the after each as well + if (this.currentTest?.state === "passed") { + done(logErrors); + } else { + done(); + } + if (resetAfterEach) { + provider.reset(); + } + }); + }); + }; +} + +/** + * Get versioned APIs for the given config. + */ +function getVersionedApis(): CompatApis { + return { + containerRuntime: ContainerRuntimeApi, + dataRuntime: DataRuntimeApi, + dds: DataRuntimeApi.dds, + driver: LocalDriverApi, + loader: LoaderApi, + }; +} + +/** + * @internal + */ +export interface ITestObjectProviderOptions { + /** If true, resets all state after each test completes. */ + resetAfterEach?: boolean; + /** If true, synchronizes summarizer client as well when ensureSynchronized() is called. */ + syncSummarizer?: boolean; +} + +/** + * @internal + */ +export type DescribeCompatSuite = ( + name: string, + tests: ( + this: Mocha.Suite, + provider: (options?: ITestObjectProviderOptions) => ITestObjectProvider, + apis: CompatApis + ) => void +) => Mocha.Suite | void; + +/** + * @internal + */ +export type DescribeCompat = DescribeCompatSuite & { + /** + * Like Mocha's `describe.skip`, but for compat tests. + */ + skip: DescribeCompatSuite; + + /** + * Like Mocha's `describe.only`, but for compat tests. + */ + only: DescribeCompatSuite; + + /** + * Run the test suite ignoring the compatibility matrix. In other words, all Fluid layers will + * reference the current code version. + * + * This is meant as a debug utility for e2e tests: do not check in tests that use it as they won't have any + * compat coverage (attempting to do so will fail the PR gate anyway). + */ + noCompat: DescribeCompatSuite; +}; + +function createCompatDescribe(): DescribeCompat { + const createCompatSuiteWithDefault = ( + tests: ( + this: Mocha.Suite, + provider: () => ITestObjectProvider, + apis: CompatApis + ) => void + ) => { + return createCompatSuite(tests); + }; + const d: DescribeCompat = (name: string, tests) => + describe(name, createCompatSuiteWithDefault(tests)); + d.skip = (name, tests) => + describe.skip(name, createCompatSuiteWithDefault(tests)); + + d.only = (name, tests) => + describe.only(name, createCompatSuiteWithDefault(tests)); + + d.noCompat = (name, tests) => + describe(name, createCompatSuiteWithDefault(tests)); + + return d; +} + +/** + * `describeCompat` expects 3 arguments (name: string, compatVersion: string, tests). + * There are three compatVersion options to generate different combinations, depending of the need of the tests: + * `FullCompat`: generate test variants with compat combinations that varies the version for all layers. + * `LoaderCompat`: generate test variants with compat combinations that only varies the loader version. + * Specific version (String) : specify a minimum compat version (e.g. "2.0.0-rc.1.0.0") which will be the minimum version a + * test suite will test against. This should be equal to the value of pkgVersion at the time you're writing the new test suite. + * + * @internal + */ +export const describeCompat: DescribeCompat = createCompatDescribe(); diff --git a/internal/test-utils/src/index.ts b/internal/test-utils/src/index.ts new file mode 100644 index 000000000..133e13179 --- /dev/null +++ b/internal/test-utils/src/index.ts @@ -0,0 +1,9 @@ +/*! + * Copyright (c) Microsoft Corporation and contributors. All rights reserved. + * Licensed under the MIT License. + */ + +export { + describeCompat, + ITestObjectProviderOptions, +} from "./describeCompat.js"; diff --git a/internal/test-utils/src/localDriverApi.ts b/internal/test-utils/src/localDriverApi.ts new file mode 100644 index 000000000..bded773da --- /dev/null +++ b/internal/test-utils/src/localDriverApi.ts @@ -0,0 +1,26 @@ +/*! + * Copyright (c) Microsoft Corporation and contributors. All rights reserved. + * Licensed under the MIT License. + */ + +import { + LocalDocumentServiceFactory, + LocalResolver, + createLocalResolverCreateNewRequest, +} from "@fluidframework/local-driver/legacy"; +import { LocalDeltaConnectionServer } from "@fluidframework/server-local-server"; + +/** + * @internal + */ +export const LocalDriverApi = { + LocalDocumentServiceFactory, + LocalDeltaConnectionServer, + LocalResolver, + createLocalResolverCreateNewRequest, +}; + +/** + * @internal + */ +export type LocalDriverApiType = typeof LocalDriverApi; diff --git a/internal/test-utils/src/localServerTestDriver.ts b/internal/test-utils/src/localServerTestDriver.ts new file mode 100644 index 000000000..fb0d484bb --- /dev/null +++ b/internal/test-utils/src/localServerTestDriver.ts @@ -0,0 +1,47 @@ +/*! + * Copyright (c) Microsoft Corporation and contributors. All rights reserved. + * Licensed under the MIT License. + */ +import { IRequest } from "@fluidframework/core-interfaces"; +import { + IDocumentServiceFactory, + IUrlResolver, +} from "@fluidframework/driver-definitions/legacy"; +import { + ILocalDeltaConnectionServer, + LocalDeltaConnectionServer, +} from "@fluidframework/server-local-server"; +import { ITestDriver } from "@fluid-internal/test-driver-definitions"; +import { LocalDriverApiType, LocalDriverApi } from "./localDriverApi.js"; + +/** + * @internal + */ +export class LocalServerTestDriver implements ITestDriver { + private readonly _server = LocalDeltaConnectionServer.create(); + public readonly endpointName = "local"; + public readonly type = "local"; + public readonly version = ""; + + public get server(): ILocalDeltaConnectionServer { + return this._server; + } + + constructor(private readonly api: LocalDriverApiType = LocalDriverApi) { + this._server = api.LocalDeltaConnectionServer.create(); + } + + createDocumentServiceFactory(): IDocumentServiceFactory { + return new this.api.LocalDocumentServiceFactory(this._server); + } + createUrlResolver(): IUrlResolver { + return new this.api.LocalResolver(); + } + createCreateNewRequest(testId: string): IRequest { + return this.api.createLocalResolverCreateNewRequest(testId); + } + + async createContainerUrl(testId: string): Promise { + return `http://localhost/${testId}`; + } +} diff --git a/internal/test-utils/src/testApi.ts b/internal/test-utils/src/testApi.ts new file mode 100644 index 000000000..1febf3215 --- /dev/null +++ b/internal/test-utils/src/testApi.ts @@ -0,0 +1,95 @@ +/*! + * Copyright (c) Microsoft Corporation and contributors. All rights reserved. + * Licensed under the MIT License. + */ + +// Loader API +import { Loader } from "@fluidframework/container-loader/legacy"; + +// ContainerRuntime API +import { ContainerRuntime } from "@fluidframework/container-runtime/internal"; + +// Data Runtime API +import * as agentScheduler from "@fluidframework/agent-scheduler"; +import * as cell from "@fluidframework/cell"; +import { SharedCell } from "@fluidframework/cell/internal"; +import * as counter from "@fluidframework/counter"; +import { SharedCounter } from "@fluidframework/counter/legacy"; +import * as map from "@fluidframework/map"; +import { SharedDirectory, SharedMap } from "@fluidframework/map/legacy"; +import * as matrix from "@fluidframework/matrix"; +import { SharedMatrix } from "@fluidframework/matrix/legacy"; +import * as orderedCollection from "@fluidframework/ordered-collection"; +import { ConsensusQueue } from "@fluidframework/ordered-collection/legacy"; +import * as registerCollection from "@fluidframework/register-collection"; +import { ConsensusRegisterCollection } from "@fluidframework/register-collection/legacy"; +import * as sequence from "@fluidframework/sequence"; +import { SharedString } from "@fluidframework/sequence/legacy"; +import { TestFluidObjectFactory } from "@fluidframework/test-utils/internal"; + +// ContainerRuntime and Data Runtime API +import { + ContainerRuntimeFactoryWithDefaultDataStore, + DataObject, + DataObjectFactory, +} from "@fluidframework/aqueduct/legacy"; +import * as sequenceDeprecated from "@fluid-experimental/sequence-deprecated"; + +// #region Current versions of the APIs. + +/** + * @internal + */ +export const LoaderApi = { + version: "", + Loader, +}; + +/** + * @internal + */ +export const ContainerRuntimeApi = { + version: "", + ContainerRuntime, + ContainerRuntimeFactoryWithDefaultDataStore, +}; + +/** + * @internal + */ +export const DataRuntimeApi = { + version: "", + DataObject, + DataObjectFactory, + TestFluidObjectFactory, + dds: { + SharedCell, + SharedCounter, + SharedDirectory, + SharedMap, + SharedMatrix, + ConsensusQueue, + ConsensusRegisterCollection, + SharedString, + }, + /** + * Contains all APIs from imported DDS packages. + * Keep in mind that regardless of the DataRuntime version, + * the APIs will be typechecked as if they were from the latest version. + * + * @remarks - Using these APIs in an e2e test puts additional burden on the test author and anyone making + * changes to those APIs in the future, since this will necessitate back-compat logic in the tests. + * Using non-stable APIs in e2e tests for that reason is discouraged. + */ + packages: { + cell, + counter, + map, + matrix, + orderedCollection, + registerCollection, + sequence, + sequenceDeprecated, + agentScheduler, + }, +}; diff --git a/internal/test-utils/tsconfig.json b/internal/test-utils/tsconfig.json new file mode 100644 index 000000000..dd3d111d2 --- /dev/null +++ b/internal/test-utils/tsconfig.json @@ -0,0 +1,75 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Basic Options */ + // "incremental": true, /* Enable incremental compilation */ + "target": "ES2022" /* Specify ECMAScript target version. */, + "module": "Node16", + "lib": [ + "ES2022", + "DOM" + ] /* Specify library files to be included in the compilation. */, + "allowJs": false /* Allow javascript files to be compiled. */, + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + "declaration": true /* Generates corresponding '.d.ts' file. */, + "declarationMap": true /* Generates a sourcemap for each corresponding '.d.ts' file. */, + "sourceMap": true /* Generates corresponding '.map' file. */, + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "./bin" /* Redirect output structure to the directory. */, + // "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + + /* Strict Type-Checking Options */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + + /* Module Resolution Options */ + // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + + /* Advanced Options */ + "skipLibCheck": true /* Skip type checking of declaration files. */, + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + }, + "exclude": ["bin", "node_modules"], + "include": ["test/**/*.ts"], + "files": ["src/index.ts"] +} diff --git a/internal/usage-test/.gitignore b/internal/usage-test/.gitignore new file mode 100644 index 000000000..3f8ee8abc --- /dev/null +++ b/internal/usage-test/.gitignore @@ -0,0 +1,3 @@ +# lock files not needed for usage tests +pnpm-lock.yaml +package-lock.json diff --git a/internal/usage-test/esm-test/.npmrc b/internal/usage-test/esm-test/.npmrc new file mode 100644 index 000000000..214c29d13 --- /dev/null +++ b/internal/usage-test/esm-test/.npmrc @@ -0,0 +1 @@ +registry=https://registry.npmjs.org/ diff --git a/internal/usage-test/esm-test/package.json b/internal/usage-test/esm-test/package.json new file mode 100644 index 000000000..aa8da5946 --- /dev/null +++ b/internal/usage-test/esm-test/package.json @@ -0,0 +1,20 @@ +{ + "name": "live-share-esm-test", + "version": "1.0.0", + "description": "", + "main": "src/index.js", + "type": "module", + "scripts": { + "test": "npm install && node src/index.js" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "@microsoft/live-share": "file:/../../../packages/live-share", + "fluid-framework": ">=2.40 <2.120" + }, + "devDependencies": { + "@fluidframework/test-runtime-utils": ">=2.40 <2.120" + } +} diff --git a/internal/usage-test/esm-test/src/index.js b/internal/usage-test/esm-test/src/index.js new file mode 100644 index 000000000..8ca9a378f --- /dev/null +++ b/internal/usage-test/esm-test/src/index.js @@ -0,0 +1,27 @@ +import { LiveShareClient, TestLiveShareHost } from "@microsoft/live-share"; +import { waitForDelay } from "@microsoft/live-share/internal"; +import { InsecureTokenProvider } from "@fluidframework/test-runtime-utils/internal"; + +const client = new LiveShareClient( + TestLiveShareHost.create( + new InsecureTokenProvider("", { + id: "testId", + name: "Test User", + }) + ) +); +const canUseLiveShare = client !== undefined; +const canUseLiveShareInternal = waitForDelay(10) !== undefined; + +if (!canUseLiveShare) { + process.exit(1); +} + +if (!canUseLiveShareInternal) { + process.exit(2); +} + +console.log("client", client); +console.log( + "Sucessfully imported and able to use Live Share package in esm project" +); diff --git a/internal/usage-test/pnpm-test/.npmrc b/internal/usage-test/pnpm-test/.npmrc new file mode 100644 index 000000000..214c29d13 --- /dev/null +++ b/internal/usage-test/pnpm-test/.npmrc @@ -0,0 +1 @@ +registry=https://registry.npmjs.org/ diff --git a/internal/usage-test/pnpm-test/package.json b/internal/usage-test/pnpm-test/package.json new file mode 100644 index 000000000..2c2b62a6c --- /dev/null +++ b/internal/usage-test/pnpm-test/package.json @@ -0,0 +1,22 @@ +{ + "name": "live-share-pnpm-test", + "version": "1.0.0", + "description": "", + "main": "bin/index.js", + "type": "module", + "scripts": { + "test": "pnpm install && pnpm run build && node bin/index.js", + "build": "tsc -p tsconfig.json" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "@microsoft/live-share": "file:/../../../packages/live-share", + "fluid-framework": ">=2.40 <2.120" + }, + "devDependencies": { + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", + "@types/node": "^20.14.14" + } +} diff --git a/internal/usage-test/pnpm-test/src/index.ts b/internal/usage-test/pnpm-test/src/index.ts new file mode 100644 index 000000000..6c8eb1aa8 --- /dev/null +++ b/internal/usage-test/pnpm-test/src/index.ts @@ -0,0 +1,27 @@ +import { LiveShareClient, TestLiveShareHost } from "@microsoft/live-share"; +import { waitForDelay } from "@microsoft/live-share/internal"; +import { InsecureTokenProvider } from "@fluidframework/test-runtime-utils/internal"; + +const client = new LiveShareClient( + TestLiveShareHost.create( + new InsecureTokenProvider("", { + id: "testId", + name: "Test User", + }) + ) +); +const canUseLiveShare = client !== undefined; +const canUseLiveShareInternal = waitForDelay(10) !== undefined; + +if (!canUseLiveShare) { + process.exit(1); +} + +if (!canUseLiveShareInternal) { + process.exit(2); +} + +console.log("client", client); +console.log( + "Sucessfully imported and able to use Live Share package in pnpm typescript esm project" +); diff --git a/internal/usage-test/pnpm-test/tsconfig.json b/internal/usage-test/pnpm-test/tsconfig.json new file mode 100644 index 000000000..ba9e3af12 --- /dev/null +++ b/internal/usage-test/pnpm-test/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "module": "Node16", + "moduleResolution": "Node16", + "outDir": "./bin", + "rootDir": "./src", + "composite": true, + "declaration": true, + "declarationMap": true, + "esModuleInterop": true, + "incremental": true, + "inlineSources": true, + "jsx": "react", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "noImplicitAny": false, + "noUnusedLocals": true, + "pretty": true, + "sourceMap": true, + "strict": true, + "target": "ES2020", + "types": ["node"], + "skipLibCheck": true + }, + "files": ["src/index.ts"] +} diff --git a/package-lock.json b/package-lock.json index b2fb8e380..655d246e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,143 +13,149 @@ "packages/live-share-acs", "packages/live-share-canvas", "packages/live-share-media", - "packages/live-share-turbo", "packages/live-share-react", + "internal/test-utils", "samples/javascript/*", "samples/typescript/*" ], "devDependencies": { - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.7", - "eslint": "^8.41.0", - "eslint-config-prettier": "^8.8.0", - "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-react": "^7.32.2", - "eslint-plugin-react-hooks": "^4.6.0", - "prettier": "^2.8.8", - "sxh": "^1.0.0", - "typedoc": "^0.24.6", - "typescript": "^5.0.4" - } - }, - "node_modules/@adobe/css-tools": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.1.tgz", - "integrity": "sha512-/62yikz7NLScCGAAST5SHdnjaDJQBDq0M2muyRTpf2VQhw6StBg2ALiu73zSJQ4fMVLA+0uBhBHAle7Wg+2kSg==" - }, - "node_modules/@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", - "dev": true, + "@types/react": "18.3.28", + "@types/react-dom": "18.3.7", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-react": "^7.34.4", + "eslint-plugin-react-hooks": "^4.6.2", + "prettier": "^3.3.3", + "typescript": "~5.5.3" + } + }, + "internal/test-utils": { + "name": "@live-share-private/test-utils", + "version": "1.0.0", + "license": "MIT", "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@fluid-experimental/attributor": "^2.0.0", + "@fluid-experimental/sequence-deprecated": "^2.0.0", + "@fluid-internal/test-driver-definitions": "^2.0.0", + "@fluidframework/agent-scheduler": "^2.0.0", + "@fluidframework/aqueduct": "^2.0.0", + "@fluidframework/cell": "^2.0.0", + "@fluidframework/container-loader": "^2.0.0", + "@fluidframework/container-runtime": "^2.0.0", + "@fluidframework/core-interfaces": "^2.0.0", + "@fluidframework/core-utils": "^2.0.0", + "@fluidframework/counter": "^2.0.0", + "@fluidframework/datastore-definitions": "^2.0.0", + "@fluidframework/driver-definitions": "^2.0.0", + "@fluidframework/local-driver": "^2.0.0", + "@fluidframework/map": "^2.0.0", + "@fluidframework/matrix": "^2.0.0", + "@fluidframework/ordered-collection": "^2.0.0", + "@fluidframework/register-collection": "^2.0.0", + "@fluidframework/runtime-definitions": "^2.0.0", + "@fluidframework/sequence": "^2.0.0", + "@fluidframework/server-local-server": "^7.0.0", + "@fluidframework/telemetry-utils": "^2.0.0", + "@fluidframework/test-utils": "^2.0.0" }, - "engines": { - "node": ">=6.0.0" + "devDependencies": { + "@fluidframework/eslint-config-fluid": "^8.1.0", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "eslint": "^8.56.0", + "eslint-plugin-unused-imports": "^3.1.0", + "mocha-json-output-reporter": "^2.0.1", + "mocha-multi-reporters": "^1.5.1", + "prettier": "^3.3.3", + "rimraf": "^4.4.0", + "typescript": "~5.5.3" } }, - "node_modules/@azure/abort-controller": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.1.0.tgz", - "integrity": "sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw==", + "internal/test-utils/node_modules/glob": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, + "license": "ISC", "dependencies": { - "tslib": "^2.2.0" + "fs.realpath": "^1.0.0", + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" }, "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/communication-calling": { - "version": "1.24.1", - "resolved": "https://registry.npmjs.org/@azure/communication-calling/-/communication-calling-1.24.1.tgz", - "integrity": "sha512-hjAazjrPU6GufexAaGOTBf9dOTM/8CNVRbzR1YusD1zhEdB8NE/xsCFcFemYOIv7ewPNKHIXVD0tmoG5mO4mjQ==", - "dev": true, - "dependencies": { - "@azure/communication-common": "^2.3.0", - "@azure/logger": "^1.0.3" - } - }, - "node_modules/@azure/communication-common": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@azure/communication-common/-/communication-common-2.3.1.tgz", - "integrity": "sha512-6ZQt20iMZbyckQn4m1TDwiDv3Fzyt1h4lnQ1szBBns2x3VQY9XHbnskPtvUdwK/HT+c/1PoUwof3toy1AIznbQ==", - "dev": true, - "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-rest-pipeline": "^1.3.2", - "@azure/core-tracing": "^1.0.0", - "@azure/core-util": "^1.0.0", - "events": "^3.0.0", - "jwt-decode": "^4.0.0", - "tslib": "^2.2.0" + "node": ">=16 || 14 >=14.17" }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@azure/communication-common/node_modules/jwt-decode": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", - "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", - "dev": true, - "engines": { - "node": ">=18" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@azure/core-auth": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.7.2.tgz", - "integrity": "sha512-Igm/S3fDYmnMq1uKS38Ae1/m37B3zigdlZw+kocwEhh5GjyKjPrXKO2J6rzpC1wAxrNil/jX9BJRqBshyjnF3g==", + "internal/test-utils/node_modules/minimatch": { + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.7.tgz", + "integrity": "sha512-V+1uQNdzybxa14e/p00HZnQNNcTjnRJjDxg2V8wtkjFctq4M7hXFws4oekyTP0Jebeq7QYtpFyOeBAjc88zvYg==", "dev": true, + "license": "ISC", "dependencies": { - "@azure/abort-controller": "^2.0.0", - "@azure/core-util": "^1.1.0", - "tslib": "^2.6.2" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=18.0.0" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@azure/core-auth/node_modules/@azure/abort-controller": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", - "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "internal/test-utils/node_modules/rimraf": { + "version": "4.4.1", "dev": true, + "license": "ISC", "dependencies": { - "tslib": "^2.6.2" + "glob": "^9.2.0" + }, + "bin": { + "rimraf": "dist/cjs/src/bin.js" }, "engines": { - "node": ">=18.0.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@azure/core-rest-pipeline": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.16.0.tgz", - "integrity": "sha512-CeuTvsXxCUmEuxH5g/aceuSl6w2EugvNHKAtKKVdiX915EjJJxAwfzNNWZreNnbxHZ2fi0zaM6wwS23x2JVqSQ==", + "node_modules/@adobe/css-tools": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.5.0.tgz", + "integrity": "sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q==", + "license": "MIT" + }, + "node_modules/@azure-rest/core-client": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@azure-rest/core-client/-/core-client-2.7.0.tgz", + "integrity": "sha512-rL0lJqh1E8HLXNgjIw8cRyGAV/v+m6p1xRu/8OhsnmN8XHhwkyYJkAoGM+zrew96v7jZYPmVfy7pv7v4Iccfsg==", "dev": true, + "license": "MIT", "dependencies": { - "@azure/abort-controller": "^2.0.0", - "@azure/core-auth": "^1.4.0", - "@azure/core-tracing": "^1.0.1", - "@azure/core-util": "^1.9.0", - "@azure/logger": "^1.0.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.0", + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.10.0", + "@azure/core-rest-pipeline": "^1.24.0", + "@azure/core-tracing": "^1.3.0", + "@typespec/ts-http-runtime": "^0.3.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, - "node_modules/@azure/core-rest-pipeline/node_modules/@azure/abort-controller": { + "node_modules/@azure/abort-controller": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^2.6.2" }, @@ -157,199 +163,160 @@ "node": ">=18.0.0" } }, - "node_modules/@azure/core-rest-pipeline/node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "node_modules/@azure/communication-calling": { + "version": "1.43.1", + "resolved": "https://registry.npmjs.org/@azure/communication-calling/-/communication-calling-1.43.1.tgz", + "integrity": "sha512-2LecMikWanbcKQP1RiiP4Ojv+7zo+jLI0Dxvbr7eUUG+GHkBMEXVoH2r/nspk4cjXgmtOcHWddPaCnagqVmbEA==", "dev": true, + "license": "Microsoft Software License Terms for the Azure Communications Services, Azure CPaaS, ACS Software Development Kit SDK, see LICENSE file", "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" + "@azure/communication-common": "^2.4.0", + "@azure/logger": "^1.0.3" } }, - "node_modules/@azure/core-rest-pipeline/node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "node_modules/@azure/communication-common": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@azure/communication-common/-/communication-common-2.4.2.tgz", + "integrity": "sha512-5ZdPoBPmXG5+tlvCIZ9lnLxunZd8a9NCQunYJHLcaNJGTsg3ZXaHczel2ByP5PnHyLJIJNor9oHJsv6gY65oYg==", "dev": true, + "license": "MIT", "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" + "@azure-rest/core-client": "^2.3.3", + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.9.0", + "@azure/core-rest-pipeline": "^1.17.0", + "@azure/core-tracing": "^1.2.0", + "@azure/core-util": "^1.11.0", + "events": "^3.3.0", + "jwt-decode": "^4.0.0", + "tslib": "^2.8.1" }, "engines": { - "node": ">= 14" + "node": ">=20.0.0" } }, - "node_modules/@azure/core-rest-pipeline/node_modules/https-proxy-agent": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", - "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", + "node_modules/@azure/core-auth": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.10.1.tgz", + "integrity": "sha512-ykRMW8PjVAn+RS6ww5cmK9U2CyH9p4Q88YJwvUslfuMmN98w/2rdGRLPqJYObapBCdzBVeDgYWdJnFPFb7qzpg==", "dev": true, + "license": "MIT", "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" + "@azure/abort-controller": "^2.1.2", + "@azure/core-util": "^1.13.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">= 14" + "node": ">=20.0.0" } }, - "node_modules/@azure/core-tracing": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.1.2.tgz", - "integrity": "sha512-dawW9ifvWAWmUm9/h+/UQ2jrdvjCJ7VJEuCJ6XVNudzcOwm53BFZH4Q845vjfgoUAM8ZxokvVNxNxAITc502YA==", + "node_modules/@azure/core-rest-pipeline": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.24.0.tgz", + "integrity": "sha512-PpLsoDQ3AMmKZ0VU+0GrmqMxgp/sExjlVm4R+nLWngeoEGAzOIPVifaxKGU5gMv+nWELUoHfvrolWD+ZS/nFJg==", "dev": true, + "license": "MIT", "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.10.0", + "@azure/core-tracing": "^1.3.0", + "@azure/core-util": "^1.13.0", + "@azure/logger": "^1.3.0", + "@typespec/ts-http-runtime": "^0.3.4", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, - "node_modules/@azure/core-util": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.9.0.tgz", - "integrity": "sha512-AfalUQ1ZppaKuxPPMsFEUdX6GZPB3d9paR9d/TTL7Ow2De8cJaC7ibi7kWVlFAVPCYo31OcnGymc0R89DX8Oaw==", + "node_modules/@azure/core-tracing": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.3.1.tgz", + "integrity": "sha512-9MWKevR7Hz8kNzzPLfX4EAtGM2b8mr50HPDBvio96bURP/9C+HjdH3sBlLSNNrvRAr5/k/svoH457gB5IKpmwQ==", "dev": true, + "license": "MIT", "dependencies": { - "@azure/abort-controller": "^2.0.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, - "node_modules/@azure/core-util/node_modules/@azure/abort-controller": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", - "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "node_modules/@azure/core-util": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.13.1.tgz", + "integrity": "sha512-XPArKLzsvl0Hf0CaGyKHUyVgF7oDnhKoP85Xv6M4StF/1AhfORhZudHtOyf2s+FcbuQ9dPRAjB8J2KvRRMUK2A==", "dev": true, + "license": "MIT", "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@typespec/ts-http-runtime": "^0.3.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, "node_modules/@azure/logger": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.1.2.tgz", - "integrity": "sha512-l170uE7bsKpIU6B/giRc9i4NI0Mj+tANMMMxf7Zi/5cKzEqPayP7+X1WPrG7e+91JgY8N+7K7nF2WOi7iVhXvg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.3.0.tgz", + "integrity": "sha512-fCqPIfOcLE+CGqGPd66c8bZpwAji98tZ4JI9i/mlTNTlsIWslCfpg48s/ypyLxZTump5sypjrKn2/kY7q8oAbA==", "dev": true, + "license": "MIT", "dependencies": { + "@typespec/ts-http-runtime": "^0.3.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, "node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "license": "MIT", "dependencies": { - "@babel/highlight": "^7.22.13", - "chalk": "^2.4.2" + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/code-frame/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/code-frame/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/code-frame/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/compat-data": { - "version": "7.21.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.7.tgz", - "integrity": "sha512-KYMqFYTaenzMK4yUtf4EW9wc4N9ef80FsbMtkwool5zpwl4YrT1SdWYSTRcT94KO4hannogdS+LxY7L+arP3gA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.21.8", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.8.tgz", - "integrity": "sha512-YeM22Sondbo523Sz0+CirSPnbj9bG3P0CdHcBZdqUuaeOaYEFbOLoGU7lebvGP6P5J/WE9wOn7u7C4J9HvS1xQ==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.5", - "@babel/helper-compilation-targets": "^7.21.5", - "@babel/helper-module-transforms": "^7.21.5", - "@babel/helpers": "^7.21.5", - "@babel/parser": "^7.21.8", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.5", - "@babel/types": "^7.21.5", - "convert-source-map": "^1.7.0", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.0" + "json5": "^2.2.3", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -364,42 +331,43 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", + "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.23.0", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.5.tgz", - "integrity": "sha512-1RkbFGUKex4lvsB9yhIfWltJM5cZKUftB2eNajaDv3dCMEp49iBG0K14uH8NnX9IPux2+mK7JGEOB0jn48/J6w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.21.5", - "@babel/helper-validator-option": "^7.21.0", - "browserslist": "^4.21.3", + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", "lru-cache": "^5.1.1", - "semver": "^6.3.0" + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { @@ -407,230 +375,115 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz", - "integrity": "sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.21.4" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.5.tgz", - "integrity": "sha512-bI2Z9zBGY2q5yMHoBvJ2a9iX3ZOAzJPm7Q8Yz6YeoUjU/Cvhmi2G4QyTNyPBqqXSgTjUxRg3L0xV45HvkNWWBw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.21.5", - "@babel/helper-module-imports": "^7.21.4", - "@babel/helper-simple-access": "^7.21.5", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.5", - "@babel/types": "^7.21.5" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.21.5.tgz", - "integrity": "sha512-0WDaIlXKOX/3KfBK/dwP1oQGiPh6rjMkT7HIRv7i5RR2VUMwrx5ZL0dwBkKx7+SW1zwNdgjHd34IMk5ZjTeHVg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.21.5.tgz", - "integrity": "sha512-ENPDAMC1wAjR0uaCUwliBdiSl1KBJAVnMTzXqi64c2MG8MPR6ii4qf7bSXDqSFbr4W6W028/rf5ivoHop5/mkg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.21.5" }, - "engines": { - "node": ">=6.9.0" + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "node_modules/@babel/helper-plugin-utils": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", - "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.5.tgz", - "integrity": "sha512-BSY+JSlHxOmGsPTydUkPf1MdMQ3M81x5xGCOVgWM3G8XH77sJ292Y2oqcp0CbbgxhqBuI46iUz1tT7hqP7EfgA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.5", - "@babel/types": "^7.21.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", - "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, "bin": { "parser": "bin/babel-parser.js" }, @@ -639,12 +492,13 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.21.0.tgz", - "integrity": "sha512-f/Eq+79JEu+KUANFks9UZCcvydOOGMgF7jBrcwjHa5jTZD8JivnhCJYvmlhR/WTXBWonDExPoW0eO/CR4QJirA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.29.7.tgz", + "integrity": "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -654,12 +508,13 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.19.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.19.6.tgz", - "integrity": "sha512-RpAi004QyMNisst/pvSanoRdJ4q+jMCWyk9zdw/CyLB9j8RXEahodR6l2GyttDRyEVWZtbN+TpLiHJ3t34LbsQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.29.7.tgz", + "integrity": "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.19.0" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -669,487 +524,648 @@ } }, "node_modules/@babel/runtime": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.5.tgz", - "integrity": "sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q==", - "dependencies": { - "regenerator-runtime": "^0.13.11" - }, + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "debug": "^4.1.0", - "globals": "^11.1.0" + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", + "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7", + "debug": "^4.3.1" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babylonjs/core": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@babylonjs/core/-/core-6.21.0.tgz", - "integrity": "sha512-8g+HPZ1aNKoqad/lq85iYngtGZIJh40Hkk2ybj9ilZOk53VAp6qYdm5TFCFhsYjuQeWzFT5a4QtiwskC8S8DUg==" + "version": "6.43.0", + "resolved": "https://registry.npmjs.org/@babylonjs/core/-/core-6.43.0.tgz", + "integrity": "sha512-pLFvvtC26TeICUcF0YjuuQqvCahJwPlATXnJkvBzMWXXxUE0Y5rI8L28iScu2WKy975605KdccJI5VL2NG7sUQ==", + "license": "Apache-2.0" }, "node_modules/@babylonjs/gui": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@babylonjs/gui/-/gui-6.21.0.tgz", - "integrity": "sha512-1aDUy5wd9ysI3V8ScLzDkdIUFdqyE5k3kWl3iJ9iPKIJuZXfIWjK2Do0QbxDrd0gsAuRE97ZgZry3gVBcXfkbw==", - "peer": true, + "version": "6.43.0", + "resolved": "https://registry.npmjs.org/@babylonjs/gui/-/gui-6.43.0.tgz", + "integrity": "sha512-iYsB7uyC40w0QkFGcPw8jAzE26jsgTFvWHTVKPSZxjQ5cG2RQEeK3aD8l+GvWauSc2qPB0wMOsvkAtusdy1g7g==", + "license": "Apache-2.0", "peerDependencies": { "@babylonjs/core": "^6.0.0" } }, "node_modules/@babylonjs/loaders": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@babylonjs/loaders/-/loaders-6.21.0.tgz", - "integrity": "sha512-pxliefbWQTu0Etr0YcLkKgxQDVQRPi+KU2yYcTyljlxyQlW0qMIa0+y3Z+N5yV3SSZRVLaXsPiLHq1td5mR7Cg==", + "version": "6.43.0", + "resolved": "https://registry.npmjs.org/@babylonjs/loaders/-/loaders-6.43.0.tgz", + "integrity": "sha512-+cgw4NDchjc/5dZYGzOEhJU+9++ygYlA+ChybE5yvF+yUDWZ7fGXnEXMFImXeFELjk5RRK1NS3H3YvPe7A+Rug==", + "license": "Apache-2.0", "peerDependencies": { "@babylonjs/core": "^6.0.0", "babylonjs-gltf2interface": "^6.0.0" } }, + "node_modules/@ctrl/tinycolor": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", + "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@emotion/hash": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", - "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", + "license": "MIT" + }, + "node_modules/@es-joy/jsdoccomment": { + "version": "0.56.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.56.0.tgz", + "integrity": "sha512-c6EW+aA1w2rjqOMjbL93nZlwxp6c1Ln06vTYs5FjRRhmJXK8V/OrSXdT+pUr4aRYgjCgu8/OkiZr0tzeVrRSbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.8", + "@typescript-eslint/types": "^8.42.0", + "comment-parser": "1.4.1", + "esquery": "^1.6.0", + "jsdoc-type-pratt-parser": "~5.1.0" + }, + "engines": { + "node": ">=20.11.0" + } + }, + "node_modules/@es-joy/jsdoccomment/node_modules/@typescript-eslint/types": { + "version": "8.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.62.0.tgz", + "integrity": "sha512-KvAclkktORPvM54TgLgA4z9HIV1M8zOgw9ZVNXl9f/8dLYfXYX1wkMXP7qmabpijQRV5bHJLOmoyGQbLMaUYeg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } }, "node_modules/@esbuild/android-arm": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz", - "integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz", - "integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz", - "integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz", - "integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz", - "integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz", - "integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz", - "integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz", - "integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz", - "integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz", - "integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz", - "integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", "cpu": [ "loong64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz", - "integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", "cpu": [ "mips64el" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz", - "integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", "cpu": [ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz", - "integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", "cpu": [ "riscv64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz", - "integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", "cpu": [ "s390x" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz", - "integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz", - "integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "netbsd" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz", - "integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "openbsd" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz", - "integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "sunos" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz", - "integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz", - "integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz", - "integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "dev": true, + "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, + "funding": { + "url": "https://opencollective.com/eslint" + }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "node_modules/@eslint-community/regexpp": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", - "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", - "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.5.2", + "espree": "^9.6.0", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -1164,2421 +1180,3439 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@eslint/js": { - "version": "8.41.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.41.0.tgz", - "integrity": "sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", "dev": true, + "license": "MIT", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@floating-ui/core": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.2.6.tgz", - "integrity": "sha512-EvYTiXet5XqweYGClEmpu3BoxmsQ4hkj3QaYA6qEnigCWffTP3vNRwBReTdrwDwo7OoJ3wM8Uoe9Uk4n+d4hfg==" + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz", + "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/devtools": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@floating-ui/devtools/-/devtools-0.2.3.tgz", + "integrity": "sha512-ZTcxTvgo9CRlP7vJV62yCxdqmahHTGpSTi5QaTDgGoyQq0OyjaVZhUhXv/qdkQFOI3Sxlfmz0XGG4HaZMsDf8Q==", + "license": "MIT", + "peerDependencies": { + "@floating-ui/dom": "^1.0.0" + } }, "node_modules/@floating-ui/dom": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.2.8.tgz", - "integrity": "sha512-XLwhYV90MxiHDq6S0rzFZj00fnDM+A1R9jhSioZoMsa7G0Q0i+Q4x40ajR8FHSdYDE1bgjG45mIWe6jtv9UPmg==", + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz", + "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", + "license": "MIT", "dependencies": { - "@floating-ui/core": "^1.2.6" + "@floating-ui/core": "^1.7.5", + "@floating-ui/utils": "^0.2.11" } }, + "node_modules/@floating-ui/utils": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz", + "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==", + "license": "MIT" + }, "node_modules/@fluentui/keyboard-keys": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/@fluentui/keyboard-keys/-/keyboard-keys-9.0.3.tgz", - "integrity": "sha512-40KBVJ9HzsvmPL3rwYaAvxCacNS0xnTmOt6TLxxrAVgVrZ1X7DLgd8OGFZcWROs0dhHdCk2D51bl4nK8Q1r3mQ==", + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@fluentui/keyboard-keys/-/keyboard-keys-9.0.8.tgz", + "integrity": "sha512-iUSJUUHAyTosnXK8O2Ilbfxma+ZyZPMua5vB028Ys96z80v+LFwntoehlFsdH3rMuPsA8GaC1RE7LMezwPBPdw==", + "license": "MIT", "dependencies": { - "@swc/helpers": "^0.4.14" + "@swc/helpers": "^0.5.1" } }, "node_modules/@fluentui/priority-overflow": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/@fluentui/priority-overflow/-/priority-overflow-9.0.3.tgz", - "integrity": "sha512-lOUfZX3PMyb+nHWcNGQu+EBz2cvRxHgTObG97UTmGBB0nL0cEJCqVL7PKVWhto7zp3moSgRUWyUN/EQVVpZ/hg==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/@fluentui/priority-overflow/-/priority-overflow-9.4.0.tgz", + "integrity": "sha512-NwhNNwCTbXYdLYwa6Ha484qCLHgRFo5vOv7BGaq0REcY2rkgwcDHVlbchwsGV7D3XgTZCjzDu54SSPmk5NOxXA==", + "license": "MIT", "dependencies": { - "@swc/helpers": "^0.4.14" + "@swc/helpers": "^0.5.1" } }, "node_modules/@fluentui/react-accordion": { - "version": "9.1.12", - "resolved": "https://registry.npmjs.org/@fluentui/react-accordion/-/react-accordion-9.1.12.tgz", - "integrity": "sha512-jFQS5xwPYLGpgSNfb1PxhmEzaP4FMxTE7tpOkqWpbpBYZ0Ed95wM1KDejr3twTsanP8Is04y/IfA9w2zGVLPdQ==", + "version": "9.12.1", + "resolved": "https://registry.npmjs.org/@fluentui/react-accordion/-/react-accordion-9.12.1.tgz", + "integrity": "sha512-F7xVaP0OR7JMCxrBwI3ryNhKof9Yi2c6RhYPsQy7rh2+KMGLGgYLsrDJyHmSejjxp4Bs11plXGdU38SN5j1hgw==", + "license": "MIT", "dependencies": { - "@fluentui/react-aria": "^9.3.20", - "@fluentui/react-context-selector": "^9.1.20", - "@fluentui/react-icons": "^2.0.196", - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-tabster": "^9.7.1", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@fluentui/react-aria": "^9.17.13", + "@fluentui/react-context-selector": "^9.2.18", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-motion": "^9.16.1", + "@fluentui/react-motion-components-preview": "^0.15.6", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0", - "scheduler": "^0.19.0 || ^0.20.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-alert": { - "version": "9.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@fluentui/react-alert/-/react-alert-9.0.0-beta.47.tgz", - "integrity": "sha512-zTW1DdaWNF3PkG9P2Hcoe+hTtd+14zifZrKi0hDS/DVG9oSpKyJiQApN3qsvwbsUaEdefY6nwK0JhT1vooERfQ==", + "version": "9.0.0-beta.141", + "resolved": "https://registry.npmjs.org/@fluentui/react-alert/-/react-alert-9.0.0-beta.141.tgz", + "integrity": "sha512-2V/DJzW56R7bjw5IRx4R8Bprn6GNcRrFzmYZyOZ8xpRxPA0BXHRnMexKtO6FQna6s6td3FCffmkpXMjyrE2bjA==", + "license": "MIT", "dependencies": { - "@fluentui/react-avatar": "^9.5.1", - "@fluentui/react-button": "^9.3.12", - "@fluentui/react-icons": "^2.0.196", - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-tabster": "^9.7.1", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@fluentui/react-avatar": "^9.11.3", + "@fluentui/react-button": "^9.10.0", + "@fluentui/react-icons": "^2.0.239", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-aria": { - "version": "9.3.20", - "resolved": "https://registry.npmjs.org/@fluentui/react-aria/-/react-aria-9.3.20.tgz", - "integrity": "sha512-KyYkcQpckarOuTlHZVONiQ2STyBmvizrZyQ2YOcSxt68yDqV1limpKZF58jslM9wlZucch2bJfVdUna/0PL+IA==", + "version": "9.17.13", + "resolved": "https://registry.npmjs.org/@fluentui/react-aria/-/react-aria-9.17.13.tgz", + "integrity": "sha512-f5qSP5aD2ZbYgQn4hCjQzqh8mHJNeN/vsC9Nwth5uJlGNdIAPbPO+dXVC18DkYqNU8O9A5Ae/uJPRbxoH23zbA==", + "license": "MIT", "dependencies": { - "@fluentui/keyboard-keys": "^9.0.3", - "@fluentui/react-utilities": "^9.9.0", - "@swc/helpers": "^0.4.14" + "@fluentui/keyboard-keys": "^9.0.8", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-utilities": "^9.26.5", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-avatar": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-avatar/-/react-avatar-9.5.1.tgz", - "integrity": "sha512-2YRXy5caXpkvKKLwDIG1qym/GoYXVo2Y+LXIogXC3d8T5cWEj1yH4bLyUYvo8yN3Gm7psCtfZN4dNnTkqrUBNw==", - "dependencies": { - "@fluentui/react-badge": "^9.1.12", - "@fluentui/react-context-selector": "^9.1.20", - "@fluentui/react-icons": "^2.0.196", - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-popover": "^9.5.12", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-tabster": "^9.7.1", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-tooltip": "^9.2.12", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" - }, - "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0", - "scheduler": "^0.19.0 || ^0.20.0" + "version": "9.11.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-avatar/-/react-avatar-9.11.3.tgz", + "integrity": "sha512-O8PoDUf1OUXDviECFvxdxo88kCEJLlP4TtCXyE58PKuAywrVeqmOA7eNy6/xhaGVuyDO8l9YJh05sYkyLiNLIQ==", + "license": "MIT", + "dependencies": { + "@fluentui/react-badge": "^9.5.4", + "@fluentui/react-context-selector": "^9.2.18", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-popover": "^9.14.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-tooltip": "^9.10.3", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-badge": { - "version": "9.1.12", - "resolved": "https://registry.npmjs.org/@fluentui/react-badge/-/react-badge-9.1.12.tgz", - "integrity": "sha512-jDfx4FJE6NfFubU1Z1NjQlMi/Z/uR3X8QQF09qGZjPRfnItM/mwp6FYik9gRFT7L31sgBRyemaCuirOApx7O/g==", + "version": "9.5.4", + "resolved": "https://registry.npmjs.org/@fluentui/react-badge/-/react-badge-9.5.4.tgz", + "integrity": "sha512-jxS6H6+KCk62MeueCf7cT2fRbdnN6h/lCOIyXWJLpPf9Mx+LWWP3KAfKik3BuDY28oy1pDYIuvFucDL+OMAb/Q==", + "license": "MIT", "dependencies": { - "@fluentui/react-icons": "^2.0.196", - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, - "node_modules/@fluentui/react-button": { - "version": "9.3.12", - "resolved": "https://registry.npmjs.org/@fluentui/react-button/-/react-button-9.3.12.tgz", - "integrity": "sha512-0u43L4p64sYL4DhcIyV3xAabk80rFobUxmkrW/NjZ+kjZxyiWZ/6gQqKOWnlaxZCx/sOOJYVRBBwMCEynkFgQQ==", + "node_modules/@fluentui/react-breadcrumb": { + "version": "9.4.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-breadcrumb/-/react-breadcrumb-9.4.3.tgz", + "integrity": "sha512-MGxPTeDSCErtbIBjdPc8fvVP6MHG514qXPur5M4EMkMfMNO+CwrRqcE95Z3a0VeD4rbj11kndo+uZMZIdaVp6w==", + "license": "MIT", "dependencies": { - "@fluentui/keyboard-keys": "^9.0.3", - "@fluentui/react-aria": "^9.3.20", - "@fluentui/react-icons": "^2.0.196", - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-tabster": "^9.7.1", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@fluentui/react-aria": "^9.17.13", + "@fluentui/react-button": "^9.10.0", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-link": "^9.8.3", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, - "node_modules/@fluentui/react-card": { - "version": "9.0.10", - "resolved": "https://registry.npmjs.org/@fluentui/react-card/-/react-card-9.0.10.tgz", - "integrity": "sha512-878NKsk2253EDZpEznN5uG+ElZSAkcNTG+kBWCPJUTV8EsY2A/VztDofrdYlvmlhnufS/0jbeh1OJxE7fljpuA==", + "node_modules/@fluentui/react-button": { + "version": "9.10.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-button/-/react-button-9.10.0.tgz", + "integrity": "sha512-Fdkp91accEtl1cmhAr0jLAmW0yYWqFAgHBViFyrxMvaLoIG3N4U5UKrttoHmfvj0/Xjg4xGafRNkwH8tPQWJQA==", + "license": "MIT", "dependencies": { - "@fluentui/keyboard-keys": "^9.0.3", - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-tabster": "^9.7.1", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@fluentui/keyboard-keys": "^9.0.8", + "@fluentui/react-aria": "^9.17.13", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, - "node_modules/@fluentui/react-checkbox": { - "version": "9.1.13", - "resolved": "https://registry.npmjs.org/@fluentui/react-checkbox/-/react-checkbox-9.1.13.tgz", - "integrity": "sha512-BkPK1UoLIZqc6nRNOQ6rHNY0caWgGnbcIbPiUC0ucefg+O9vPmlffk/XD8APul/mhmjrOanOR8KZ8SsnhbIneA==", + "node_modules/@fluentui/react-card": { + "version": "9.7.1", + "resolved": "https://registry.npmjs.org/@fluentui/react-card/-/react-card-9.7.1.tgz", + "integrity": "sha512-4t65Y9pRW9W7kf/Yyc7S796le2WFKfXFTCuzfkFS+AHUM7JlrmMUOnQLA0i24WDNS6ArA0vo6EbMDnUcjgV9Yg==", + "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.1.3", - "@fluentui/react-icons": "^2.0.196", - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-label": "^9.1.12", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-tabster": "^9.7.1", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@fluentui/keyboard-keys": "^9.0.8", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-text": "^9.6.18", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" - } - }, - "node_modules/@fluentui/react-combobox": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-combobox/-/react-combobox-9.3.1.tgz", - "integrity": "sha512-2PZQkNM0ppdNQs5J33ABk6zTAqNoC9L2i/hVUYPLk5KMaYnlpt5ArZsDXdSvTiCaYgKcAh35EBIZcwCkvt/oug==", - "dependencies": { - "@fluentui/keyboard-keys": "^9.0.3", - "@fluentui/react-context-selector": "^9.1.20", - "@fluentui/react-field": "^9.1.3", - "@fluentui/react-icons": "^2.0.196", - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-portal": "^9.2.8", - "@fluentui/react-positioning": "^9.5.12", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" - }, - "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0", - "scheduler": "^0.19.0 || ^0.20.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, - "node_modules/@fluentui/react-components": { - "version": "9.20.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-components/-/react-components-9.20.1.tgz", - "integrity": "sha512-UmPk6Z756gQqLNi7A/0bV6OC3ybh1i5fe1aDUhR+1JbIlRH+hgbpCWQfL3UACbTjwuw/taOQNRyAeHsxgcBzYQ==", - "dependencies": { - "@fluentui/react-accordion": "^9.1.12", - "@fluentui/react-alert": "9.0.0-beta.47", - "@fluentui/react-avatar": "^9.5.1", - "@fluentui/react-badge": "^9.1.12", - "@fluentui/react-button": "^9.3.12", - "@fluentui/react-card": "^9.0.10", - "@fluentui/react-checkbox": "^9.1.13", - "@fluentui/react-combobox": "^9.3.1", - "@fluentui/react-dialog": "^9.5.5", - "@fluentui/react-divider": "^9.2.12", - "@fluentui/react-field": "^9.1.3", - "@fluentui/react-image": "^9.1.9", - "@fluentui/react-infobutton": "9.0.0-beta.30", - "@fluentui/react-input": "^9.4.13", - "@fluentui/react-label": "^9.1.12", - "@fluentui/react-link": "^9.0.38", - "@fluentui/react-menu": "^9.7.12", - "@fluentui/react-overflow": "^9.0.17", - "@fluentui/react-persona": "^9.2.11", - "@fluentui/react-popover": "^9.5.12", - "@fluentui/react-portal": "^9.2.8", - "@fluentui/react-positioning": "^9.5.12", - "@fluentui/react-progress": "^9.1.13", - "@fluentui/react-provider": "^9.6.1", - "@fluentui/react-radio": "^9.1.13", - "@fluentui/react-select": "^9.1.13", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-skeleton": "^9.0.1", - "@fluentui/react-slider": "^9.1.13", - "@fluentui/react-spinbutton": "^9.2.13", - "@fluentui/react-spinner": "^9.1.12", - "@fluentui/react-switch": "^9.1.13", - "@fluentui/react-table": "^9.2.9", - "@fluentui/react-tabs": "^9.3.13", - "@fluentui/react-tabster": "^9.7.1", - "@fluentui/react-text": "^9.3.9", - "@fluentui/react-textarea": "^9.3.13", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-toolbar": "^9.1.13", - "@fluentui/react-tooltip": "^9.2.12", - "@fluentui/react-tree": "9.0.0-beta.14", - "@fluentui/react-utilities": "^9.9.0", - "@fluentui/react-virtualizer": "9.0.0-alpha.20", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" - }, - "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0", - "scheduler": "^0.19.0 || ^0.20.0" - } - }, - "node_modules/@fluentui/react-context-selector": { - "version": "9.1.20", - "resolved": "https://registry.npmjs.org/@fluentui/react-context-selector/-/react-context-selector-9.1.20.tgz", - "integrity": "sha512-EZ1Zj4C/TVAx715UZzjr4tbj+S4rMKqw8wOeOJXx9ewoRzCmsO705hmxRBbDPGqVtkhi/n4xWPFLmwlYwzDTZg==", + "node_modules/@fluentui/react-carousel": { + "version": "9.9.9", + "resolved": "https://registry.npmjs.org/@fluentui/react-carousel/-/react-carousel-9.9.9.tgz", + "integrity": "sha512-Cbs9Hsx37SKYBaiXvCNPg+Tp1mhN4peL5TSjEGUwXZwgry+7AQ6+zSHDa6GvIs+/EzwR627LLY6TXR/ktzovDQ==", + "license": "MIT", "dependencies": { - "@fluentui/react-utilities": "^9.9.0", - "@swc/helpers": "^0.4.14" + "@fluentui/react-aria": "^9.17.13", + "@fluentui/react-button": "^9.10.0", + "@fluentui/react-context-selector": "^9.2.18", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-tooltip": "^9.10.3", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1", + "embla-carousel": "^8.5.1", + "embla-carousel-autoplay": "^8.5.1", + "embla-carousel-fade": "^8.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0", - "scheduler": "^0.19.0 || ^0.20.0" - } - }, - "node_modules/@fluentui/react-dialog": { - "version": "9.5.5", - "resolved": "https://registry.npmjs.org/@fluentui/react-dialog/-/react-dialog-9.5.5.tgz", - "integrity": "sha512-9o7zC8t68WU/oAOsROb+63SLn6orPsGDyWH19lgYvBJn/hmAEQXWDL4KO3dbW+6X1okaxLRrZw+oYTqEF+2HmQ==", - "dependencies": { - "@fluentui/keyboard-keys": "^9.0.3", - "@fluentui/react-aria": "^9.3.20", - "@fluentui/react-context-selector": "^9.1.20", - "@fluentui/react-icons": "^2.0.196", - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-portal": "^9.2.8", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-tabster": "^9.7.1", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" - }, - "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, - "node_modules/@fluentui/react-divider": { - "version": "9.2.12", - "resolved": "https://registry.npmjs.org/@fluentui/react-divider/-/react-divider-9.2.12.tgz", - "integrity": "sha512-6T/JTDyjotCGp/Dn7AAjZ/dXYg1D0bMIMGHy1B8wCnF2DHJD7un4YvQ19QKloBEmimEHK4UUKRvqvvJO1aeOyg==", + "node_modules/@fluentui/react-checkbox": { + "version": "9.6.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-checkbox/-/react-checkbox-9.6.3.tgz", + "integrity": "sha512-VzePhN5Nz3D69Fu7SnPUCrMfkrbhfqGpNJDis85+W7dvOo9cyUou6yRreHsSzxVkRyE9swcA1LnsKJS6oVn9ew==", + "license": "MIT", "dependencies": { - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@fluentui/react-field": "^9.5.3", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-label": "^9.4.3", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, - "node_modules/@fluentui/react-field": { - "version": "9.1.3", - "resolved": "https://registry.npmjs.org/@fluentui/react-field/-/react-field-9.1.3.tgz", - "integrity": "sha512-U7+Wt9+ZGMoBRGMo3SkqD7huvzEGgwDXc/+8P7A3YSuy0ycVruDWgLyspcqWJ5ULMOheYt3yiK21JpJVbhl36A==", + "node_modules/@fluentui/react-color-picker": { + "version": "9.2.18", + "resolved": "https://registry.npmjs.org/@fluentui/react-color-picker/-/react-color-picker-9.2.18.tgz", + "integrity": "sha512-zbsQ+hVJeGwXVTjneA42i4UuHRACfcTnBs3BUcDT22lBDQjJxhYYZzmj5ksM92M2ZU0fMHV8K5OfSyCnZU5mqQ==", + "license": "MIT", "dependencies": { - "@fluentui/react-context-selector": "^9.1.20", - "@fluentui/react-icons": "^2.0.196", - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-label": "^9.1.12", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@ctrl/tinycolor": "^3.3.4", + "@fluentui/react-context-selector": "^9.2.18", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, - "node_modules/@fluentui/react-icons": { - "version": "2.0.202", - "resolved": "https://registry.npmjs.org/@fluentui/react-icons/-/react-icons-2.0.202.tgz", - "integrity": "sha512-QMiFMaDj99T+w3/EAdvEfDCk5hkzn6LBkqSVW2Ov+WY25/WNv54W169qmWW8LuEZLUiEYHZejwcEghaMHmswVA==", + "node_modules/@fluentui/react-combobox": { + "version": "9.17.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-combobox/-/react-combobox-9.17.3.tgz", + "integrity": "sha512-QuWcM6fvqnfUzpkJApQbXfbIQ6iQkMGgrsdwmJHkB4Q/E6zT0aLZoEjEx2P5QkMz9m5D7LzeZWmFIOEFq8SzFQ==", + "license": "MIT", "dependencies": { - "@griffel/react": "^1.0.0", - "tslib": "^2.1.0" + "@fluentui/keyboard-keys": "^9.0.8", + "@fluentui/react-aria": "^9.17.13", + "@fluentui/react-context-selector": "^9.2.18", + "@fluentui/react-field": "^9.5.3", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-portal": "^9.8.14", + "@fluentui/react-positioning": "^9.22.3", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "react": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, - "node_modules/@fluentui/react-image": { - "version": "9.1.9", - "resolved": "https://registry.npmjs.org/@fluentui/react-image/-/react-image-9.1.9.tgz", - "integrity": "sha512-kcG61Qw8Uvc+Zc0lZpSuVtMllvX83idrApnZTKqMCfHeV34OylBafcFsZLL2ijcMMFuN8yb5r/FdbtAbwXGf+Q==", + "node_modules/@fluentui/react-components": { + "version": "9.74.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-components/-/react-components-9.74.2.tgz", + "integrity": "sha512-Vih/4CEIGC30osCeX3Ns+QFcyQy279AkV6H/WM1eO0HxEF3sPYT/t6fYPKWjUvVevuxEvLsx/K+IeLRExFUXyA==", + "license": "MIT", "dependencies": { - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@fluentui/react-accordion": "^9.12.1", + "@fluentui/react-alert": "9.0.0-beta.141", + "@fluentui/react-aria": "^9.17.13", + "@fluentui/react-avatar": "^9.11.3", + "@fluentui/react-badge": "^9.5.4", + "@fluentui/react-breadcrumb": "^9.4.3", + "@fluentui/react-button": "^9.10.0", + "@fluentui/react-card": "^9.7.1", + "@fluentui/react-carousel": "^9.9.9", + "@fluentui/react-checkbox": "^9.6.3", + "@fluentui/react-color-picker": "^9.2.18", + "@fluentui/react-combobox": "^9.17.3", + "@fluentui/react-dialog": "^9.18.2", + "@fluentui/react-divider": "^9.7.3", + "@fluentui/react-drawer": "^9.13.1", + "@fluentui/react-field": "^9.5.3", + "@fluentui/react-image": "^9.4.3", + "@fluentui/react-infobutton": "9.0.0-beta.117", + "@fluentui/react-infolabel": "^9.4.22", + "@fluentui/react-input": "^9.8.4", + "@fluentui/react-label": "^9.4.3", + "@fluentui/react-link": "^9.8.3", + "@fluentui/react-list": "^9.6.16", + "@fluentui/react-menu": "^9.25.1", + "@fluentui/react-message-bar": "^9.7.2", + "@fluentui/react-motion": "^9.16.1", + "@fluentui/react-nav": "^9.4.1", + "@fluentui/react-overflow": "^9.9.0", + "@fluentui/react-persona": "^9.7.5", + "@fluentui/react-popover": "^9.14.4", + "@fluentui/react-portal": "^9.8.14", + "@fluentui/react-positioning": "^9.22.3", + "@fluentui/react-progress": "^9.5.3", + "@fluentui/react-provider": "^9.22.18", + "@fluentui/react-radio": "^9.6.4", + "@fluentui/react-rating": "^9.4.3", + "@fluentui/react-search": "^9.4.4", + "@fluentui/react-select": "^9.5.3", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-skeleton": "^9.7.4", + "@fluentui/react-slider": "^9.6.4", + "@fluentui/react-spinbutton": "^9.6.4", + "@fluentui/react-spinner": "^9.8.4", + "@fluentui/react-swatch-picker": "^9.5.4", + "@fluentui/react-switch": "^9.7.4", + "@fluentui/react-table": "^9.19.17", + "@fluentui/react-tabs": "^9.12.3", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-tag-picker": "^9.9.0", + "@fluentui/react-tags": "^9.9.2", + "@fluentui/react-teaching-popover": "^9.7.1", + "@fluentui/react-text": "^9.6.18", + "@fluentui/react-textarea": "^9.7.4", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-toast": "^9.8.1", + "@fluentui/react-toolbar": "^9.8.2", + "@fluentui/react-tooltip": "^9.10.3", + "@fluentui/react-tree": "^9.16.2", + "@fluentui/react-utilities": "^9.26.5", + "@fluentui/react-virtualizer": "9.0.0-alpha.114", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" + } + }, + "node_modules/@fluentui/react-context-selector": { + "version": "9.2.18", + "resolved": "https://registry.npmjs.org/@fluentui/react-context-selector/-/react-context-selector-9.2.18.tgz", + "integrity": "sha512-A9YdkKonDlNSTnD8SCcSMhj0O6mAyMtXMERWH5mA1UqdtVxzJ4Y/muNd3Nk5rwAaLPUZ5HWMabtt2Ewa/BxARA==", + "license": "MIT", + "dependencies": { + "@fluentui/react-utilities": "^9.26.5", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0", + "scheduler": ">=0.19.0" + } + }, + "node_modules/@fluentui/react-dialog": { + "version": "9.18.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-dialog/-/react-dialog-9.18.2.tgz", + "integrity": "sha512-acW70/CxibJC19bQVbrJyxYiuIP9nX593O/Tya4x9wMEEcnTHZ6RW8liS6kbYYEL/AERYRuOYkLJ++TNniTxSA==", + "license": "MIT", + "dependencies": { + "@fluentui/keyboard-keys": "^9.0.8", + "@fluentui/react-aria": "^9.17.13", + "@fluentui/react-context-selector": "^9.2.18", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-motion": "^9.16.1", + "@fluentui/react-motion-components-preview": "^0.15.6", + "@fluentui/react-portal": "^9.8.14", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" + } + }, + "node_modules/@fluentui/react-divider": { + "version": "9.7.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-divider/-/react-divider-9.7.3.tgz", + "integrity": "sha512-uhqpu+JfSaLEqFNtDQFYFo/gM1QoRV2I1iUYTMsO2iqEis4zZmMsQETti7lTv29SITWIky3e8pkRoC6xyQBLsg==", + "license": "MIT", + "dependencies": { + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" + } + }, + "node_modules/@fluentui/react-drawer": { + "version": "9.13.1", + "resolved": "https://registry.npmjs.org/@fluentui/react-drawer/-/react-drawer-9.13.1.tgz", + "integrity": "sha512-nZBWG0290IcCshpt2wjORDD8fLOsccSPdp0EW45CxK09/JR+4hkGbbIj8x14GW7GYu4RsGzk18OYga0kY+4j2Q==", + "license": "MIT", + "dependencies": { + "@fluentui/react-dialog": "^9.18.2", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-motion": "^9.16.1", + "@fluentui/react-motion-components-preview": "^0.15.6", + "@fluentui/react-portal": "^9.8.14", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" + } + }, + "node_modules/@fluentui/react-field": { + "version": "9.5.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-field/-/react-field-9.5.3.tgz", + "integrity": "sha512-5PJXFTGS9W4CBJW6Nh2Tqe5p8RxMMCPbsIyIcYUXIxCZTXDGrx1jZ+af8lWKJFlcfWOlFxyK+QE14UXl+lqzqw==", + "license": "MIT", + "dependencies": { + "@fluentui/react-context-selector": "^9.2.18", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-label": "^9.4.3", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" + } + }, + "node_modules/@fluentui/react-icons": { + "version": "2.0.330", + "resolved": "https://registry.npmjs.org/@fluentui/react-icons/-/react-icons-2.0.330.tgz", + "integrity": "sha512-IaJjO755FGlUR5Myy1IuhJKlqGPfET9JqGpotoanJm1W1sK2rELRv8L3i2UAiZ70TSvi6KAi5t4M0inqI/h9Nw==", + "license": "MIT", + "dependencies": { + "@griffel/react": "^1.6.1", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "react": ">=16.8.0 <20.0.0" + } + }, + "node_modules/@fluentui/react-image": { + "version": "9.4.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-image/-/react-image-9.4.3.tgz", + "integrity": "sha512-BQSsT3kVdpR3s02Zq9zpqj0NjaijWOVKPLBchp9XqWlygO15dkykNt2LRoHAkZRgpnlh2D8zBCw9qQ4ubzYNaA==", + "license": "MIT", + "dependencies": { + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-infobutton": { - "version": "9.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@fluentui/react-infobutton/-/react-infobutton-9.0.0-beta.30.tgz", - "integrity": "sha512-w2tWBlrsXSXwbMmdPpsKCTtQCIoeShPZspmnBCoKXnHSevdk4BNEjr0q5QzoSvIY2FRdxMrLmcAWJAyv4aA+AA==", + "version": "9.0.0-beta.117", + "resolved": "https://registry.npmjs.org/@fluentui/react-infobutton/-/react-infobutton-9.0.0-beta.117.tgz", + "integrity": "sha512-h01PQzH736I/7mhjNcYi8cFjspCqgSmQukXbzCsESzB1VnAkx8djqy5A8f/mV1HmHw7vBAIX8VdH+ddtx8WyXQ==", + "license": "MIT", + "dependencies": { + "@fluentui/react-icons": "^2.0.237", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-label": "^9.4.3", + "@fluentui/react-popover": "^9.14.4", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" + } + }, + "node_modules/@fluentui/react-infolabel": { + "version": "9.4.22", + "resolved": "https://registry.npmjs.org/@fluentui/react-infolabel/-/react-infolabel-9.4.22.tgz", + "integrity": "sha512-K5W+g+HfGu5ltl5BGekZJB2z0ACLidIW7KFQ5Qj+UG1kpoB3G4q10HTm5gY74VjXP/GrM5RVx8IcnHRqyAfR1Q==", + "license": "MIT", "dependencies": { - "@fluentui/react-icons": "^2.0.196", - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-label": "^9.1.12", - "@fluentui/react-popover": "^9.5.12", - "@fluentui/react-tabster": "^9.7.1", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-label": "^9.4.3", + "@fluentui/react-popover": "^9.14.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.8.0 <20.0.0", + "@types/react-dom": ">=16.8.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.8.0 <20.0.0" } }, "node_modules/@fluentui/react-input": { - "version": "9.4.13", - "resolved": "https://registry.npmjs.org/@fluentui/react-input/-/react-input-9.4.13.tgz", - "integrity": "sha512-EzhlZE81gcwqxgqsgVkh5aocK4W3WHo0FBZ50ZidQU+02GK07vsYpyABUChJtpoAdxqMMDS+3t6atcqOiFGaTw==", + "version": "9.8.4", + "resolved": "https://registry.npmjs.org/@fluentui/react-input/-/react-input-9.8.4.tgz", + "integrity": "sha512-Lpdu0TBBSbv3VasaCz3blNeEgQS7XhtLTmiYXZj5g8Hrk7gNDJORDPYRrXcRjOUPGkV/InB4JY+GeXy2cYfOaA==", + "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.1.3", - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@fluentui/react-field": "^9.5.3", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-jsx-runtime": { - "version": "9.0.0-alpha.4", - "resolved": "https://registry.npmjs.org/@fluentui/react-jsx-runtime/-/react-jsx-runtime-9.0.0-alpha.4.tgz", - "integrity": "sha512-FVsNvmExQgoYP1sil/udXLi0H5P/lLw1TXotq+e+Zam4+OdFQeCJ0HD/2jN7uRKCDLnmZILyt4ThMGYGv6z2xw==", + "version": "9.4.4", + "resolved": "https://registry.npmjs.org/@fluentui/react-jsx-runtime/-/react-jsx-runtime-9.4.4.tgz", + "integrity": "sha512-npqPWSJ2qciCRB4B/cyWyrTbf8V8Z2Kfr9HnZqrUBDgEvq72rRGb+gml6naxGNzhaT4NBLQLZmdPZqt+1wZ4ig==", + "license": "MIT", "dependencies": { - "@fluentui/react-utilities": "^9.9.0", - "@swc/helpers": "^0.4.14" + "@fluentui/react-utilities": "^9.26.5", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "react": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-label": { - "version": "9.1.12", - "resolved": "https://registry.npmjs.org/@fluentui/react-label/-/react-label-9.1.12.tgz", - "integrity": "sha512-us/OUT1/TizC3ouLCyhzDWV4Gzf+BoceqoM9CgZVYUnJbNaKQKLUiVaXmt0FhVsfPaai5mVt/NWUZMTOrxv8lA==", + "version": "9.4.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-label/-/react-label-9.4.3.tgz", + "integrity": "sha512-/tYFciaorFym7Q2yDCdRYeP3JzLtw5eYt2yCvRlmBsugtKmn2f/kOu+b2cB37kWizbXjSdOGhCrTL8J1EUlIZg==", + "license": "MIT", "dependencies": { - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-link": { - "version": "9.0.38", - "resolved": "https://registry.npmjs.org/@fluentui/react-link/-/react-link-9.0.38.tgz", - "integrity": "sha512-hDNTFg1ww27PADz7oiJqAL4T6QhZ50cmBpeRTJ0c9uksU6hA0EfEhaBoRLpFe2g/avIcLWg8oyEPhpsB8XaqpA==", + "version": "9.8.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-link/-/react-link-9.8.3.tgz", + "integrity": "sha512-3Cd+UWgLpP6E6/NZaomCqZd965gruWXz2+gqUDfP7nBTLaCgOIuFQe0HAgSYi0ys4xli3cDtKeytqZJ7ReA6gg==", + "license": "MIT", + "dependencies": { + "@fluentui/keyboard-keys": "^9.0.8", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" + } + }, + "node_modules/@fluentui/react-list": { + "version": "9.6.16", + "resolved": "https://registry.npmjs.org/@fluentui/react-list/-/react-list-9.6.16.tgz", + "integrity": "sha512-ZWsLxr1ZDe6hmvGLGlHQIPt1E70xsWHaHn+QGxB0XUxjq64SnxCDm4HCSPZ40MS3Hqgd4eQdnmPUS9d6odcYUA==", + "license": "MIT", "dependencies": { - "@fluentui/keyboard-keys": "^9.0.3", - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-tabster": "^9.7.1", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@fluentui/keyboard-keys": "^9.0.8", + "@fluentui/react-checkbox": "^9.6.3", + "@fluentui/react-context-selector": "^9.2.18", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.8.0 <20.0.0", + "@types/react-dom": ">=16.8.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.8.0 <20.0.0" } }, "node_modules/@fluentui/react-menu": { - "version": "9.7.12", - "resolved": "https://registry.npmjs.org/@fluentui/react-menu/-/react-menu-9.7.12.tgz", - "integrity": "sha512-i+yfMccvrmbLqzNuoY2LuEfsmudB98wtPs/2zwuXz7EaAeae2puEl1/844wBT3bxiX+9SY8ZJqdQejRKWq1IDg==", - "dependencies": { - "@fluentui/keyboard-keys": "^9.0.3", - "@fluentui/react-aria": "^9.3.20", - "@fluentui/react-context-selector": "^9.1.20", - "@fluentui/react-icons": "^2.0.196", - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-portal": "^9.2.8", - "@fluentui/react-positioning": "^9.5.12", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-tabster": "^9.7.1", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" - }, - "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0", - "scheduler": "^0.19.0 || ^0.20.0" + "version": "9.25.1", + "resolved": "https://registry.npmjs.org/@fluentui/react-menu/-/react-menu-9.25.1.tgz", + "integrity": "sha512-nP2bUB0Blrz5cqG6JnaHKznD2zGv134vuiCStk0op1/IErIPoU6wJj6H+unYVhFwyHCReyPZcp/pQZWkSWErJQ==", + "license": "MIT", + "dependencies": { + "@fluentui/keyboard-keys": "^9.0.8", + "@fluentui/react-aria": "^9.17.13", + "@fluentui/react-context-selector": "^9.2.18", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-motion": "^9.16.1", + "@fluentui/react-motion-components-preview": "^0.15.6", + "@fluentui/react-portal": "^9.8.14", + "@fluentui/react-positioning": "^9.22.3", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" + } + }, + "node_modules/@fluentui/react-message-bar": { + "version": "9.7.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-message-bar/-/react-message-bar-9.7.2.tgz", + "integrity": "sha512-JHejQPpyHtTMD0NY/OK/89ZGZ0QcGV5esv/4HkA+qxDOPunjV11GNjjOAHnWIGG0oBsdDOQWoM+F3hm6LOMbrA==", + "license": "MIT", + "dependencies": { + "@fluentui/react-button": "^9.10.0", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-link": "^9.8.3", + "@fluentui/react-motion": "^9.16.1", + "@fluentui/react-motion-components-preview": "^0.15.6", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.8.0 <20.0.0", + "@types/react-dom": ">=16.8.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.8.0 <20.0.0" + } + }, + "node_modules/@fluentui/react-motion": { + "version": "9.16.1", + "resolved": "https://registry.npmjs.org/@fluentui/react-motion/-/react-motion-9.16.1.tgz", + "integrity": "sha512-sbrNuauwI5uw20XOAqPjXBfgBqPreHc5AxU7bJ6yoLUHL2gDKo7KGAIvLEd216GX37mgPkb3dx9rarIVGx3uvA==", + "license": "MIT", + "dependencies": { + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-utilities": "^9.26.5", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.8.0 <20.0.0", + "@types/react-dom": ">=16.8.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.8.0 <20.0.0" + } + }, + "node_modules/@fluentui/react-motion-components-preview": { + "version": "0.15.6", + "resolved": "https://registry.npmjs.org/@fluentui/react-motion-components-preview/-/react-motion-components-preview-0.15.6.tgz", + "integrity": "sha512-9aNzHAHNdfbH/8/mYGy5YVrUOGnpiru3YrqQ7KhCRWXvlce7yV3WF5CzN1g/uNh3MFmKGwQeW4ui6xJOfEaI4Q==", + "license": "MIT", + "dependencies": { + "@fluentui/react-motion": "*", + "@fluentui/react-utilities": "*", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" + } + }, + "node_modules/@fluentui/react-nav": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/@fluentui/react-nav/-/react-nav-9.4.1.tgz", + "integrity": "sha512-7iwhmtAkqExNjjYuNU12y7I9mwup/ppHepj90IJ/dfzbv6E9qPiZ7Kql+XzBX1biT2aIZO3MC7zBdlUtRuis/g==", + "license": "MIT", + "dependencies": { + "@fluentui/react-aria": "^9.17.13", + "@fluentui/react-button": "^9.10.0", + "@fluentui/react-context-selector": "^9.2.18", + "@fluentui/react-divider": "^9.7.3", + "@fluentui/react-drawer": "^9.13.1", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-motion": "^9.16.1", + "@fluentui/react-motion-components-preview": "^0.15.6", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-tooltip": "^9.10.3", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-overflow": { - "version": "9.0.17", - "resolved": "https://registry.npmjs.org/@fluentui/react-overflow/-/react-overflow-9.0.17.tgz", - "integrity": "sha512-Z+e7R5Nt2T8myCAo3stSVWkesCAI6AOvfB1xQdS2OnhLaybAKB8bhgeDG3GqTnBFuK89ZWdTtWuNctC2Rcmp/A==", + "version": "9.9.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-overflow/-/react-overflow-9.9.0.tgz", + "integrity": "sha512-u8M7yqlzmvdYezlvVjGJUH38ik5fb59aSSGOsJyepnXM5HwnyFb9ecBwqAFAGi23lw+wz07V0aeYMEzK7q+slw==", + "license": "MIT", "dependencies": { - "@fluentui/priority-overflow": "^9.0.3", - "@fluentui/react-context-selector": "^9.1.20", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@fluentui/priority-overflow": "^9.4.0", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0", - "scheduler": "^0.19.0 || ^0.20.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-persona": { - "version": "9.2.11", - "resolved": "https://registry.npmjs.org/@fluentui/react-persona/-/react-persona-9.2.11.tgz", - "integrity": "sha512-FzmvjO5HCyCnGwE4WLduKJ6Z2PR4km44PkqwLlS9QCJHvnqLL/TX+ZvSz/R6u+2zEof7PHddXV9Cixk7hHh8xQ==", + "version": "9.7.5", + "resolved": "https://registry.npmjs.org/@fluentui/react-persona/-/react-persona-9.7.5.tgz", + "integrity": "sha512-5MlVpl3+l+UW7vTf/d1qKP6EANBkxoXjmxmbNZpiuXjIE2QJFcVRBplWXwEPgt3GAOGnix1wPVkUgHElUJOCEw==", + "license": "MIT", "dependencies": { - "@fluentui/react-avatar": "^9.5.1", - "@fluentui/react-badge": "^9.1.12", - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@fluentui/react-avatar": "^9.11.3", + "@fluentui/react-badge": "^9.5.4", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-popover": { - "version": "9.5.12", - "resolved": "https://registry.npmjs.org/@fluentui/react-popover/-/react-popover-9.5.12.tgz", - "integrity": "sha512-oYdtD+w1svU9F3opq+CpTf4ILL08XRNI64bWFiix66P4MIOZ0K3YFnMIeCZijRfQbT+h0n1Qn77XLgJGSacGyw==", - "dependencies": { - "@fluentui/keyboard-keys": "^9.0.3", - "@fluentui/react-aria": "^9.3.20", - "@fluentui/react-context-selector": "^9.1.20", - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-portal": "^9.2.8", - "@fluentui/react-positioning": "^9.5.12", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-tabster": "^9.7.1", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" - }, - "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0", - "scheduler": "^0.19.0 || ^0.20.0" + "version": "9.14.4", + "resolved": "https://registry.npmjs.org/@fluentui/react-popover/-/react-popover-9.14.4.tgz", + "integrity": "sha512-Ofn4kh+WfC647n9ap0mtoN47eP0FsP/ZIjoZf1GfW6Co+A3zAZN+V7z6AayCPvbvdv8vKFQ0diHeUBrIu9Pz3Q==", + "license": "MIT", + "dependencies": { + "@fluentui/keyboard-keys": "^9.0.8", + "@fluentui/react-aria": "^9.17.13", + "@fluentui/react-context-selector": "^9.2.18", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-motion": "^9.16.1", + "@fluentui/react-motion-components-preview": "^0.15.6", + "@fluentui/react-portal": "^9.8.14", + "@fluentui/react-positioning": "^9.22.3", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-portal": { - "version": "9.2.8", - "resolved": "https://registry.npmjs.org/@fluentui/react-portal/-/react-portal-9.2.8.tgz", - "integrity": "sha512-L5B9A9wbr7+Opcu9ggUF9aebb7TlCxCgLqJ2HSCFlb8hfeyW9+2Af2+7n9YUeYKSKBQ6Xy1T1MnggUktgODzSQ==", + "version": "9.8.14", + "resolved": "https://registry.npmjs.org/@fluentui/react-portal/-/react-portal-9.8.14.tgz", + "integrity": "sha512-od8RN6dny6N/qGFm2uv5UV+ugGOKupFeCIF+R0rU5SimSvix6o+wv5rPrH9JHRHFqjDIi5kRh9hk/rZfgsnuaA==", + "license": "MIT", "dependencies": { - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-tabster": "^9.7.1", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14", - "use-disposable": "^1.0.1" + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-positioning": { - "version": "9.5.12", - "resolved": "https://registry.npmjs.org/@fluentui/react-positioning/-/react-positioning-9.5.12.tgz", - "integrity": "sha512-NQdwaUa2sZT/Zu+QnNrKr900y8Jmp7vBx4I3fgsITQHIe4QKrffMGLU8FchQiyfrBRJhL+B2+s8s0Nef5R7vWw==", + "version": "9.22.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-positioning/-/react-positioning-9.22.3.tgz", + "integrity": "sha512-2j2k87k7yVX8LYd9q3SniXYVGqED6JFRdTNeyamDf4DTk9/ECxTl2nKTmKedkDodddR5RRXpAtJXv874Mi9eyw==", + "license": "MIT", "dependencies": { - "@floating-ui/dom": "^1.2.0", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@floating-ui/devtools": "^0.2.3", + "@floating-ui/dom": "^1.6.12", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1", + "use-sync-external-store": "^1.2.0" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-progress": { - "version": "9.1.13", - "resolved": "https://registry.npmjs.org/@fluentui/react-progress/-/react-progress-9.1.13.tgz", - "integrity": "sha512-QwFkfOS8NtlfIvFXTQirrqdPgC2mEuvFFsQO9Jb/ngIaPzfc5HAQ3wSAq0kph0+GPHb++iwYGOafmBw+iQQk1g==", + "version": "9.5.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-progress/-/react-progress-9.5.3.tgz", + "integrity": "sha512-GVrZzo9QCBOyMZC/K8Q4VTbD76hgG/Xuvhr8gyqOxnuHS9lTfnPJyEZ+T+F36LmpDb6d/XmDcwKjIcyg359ieg==", + "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.1.3", - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@fluentui/react-field": "^9.5.3", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-motion": "^9.16.1", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-provider": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-provider/-/react-provider-9.6.1.tgz", - "integrity": "sha512-Z6FZmSXKPBsHMhPuGjlnx6s1O0T56x63GAo8bHfMwJGBRCs10Z8zBo8yEkrgg+ljXmUy3Pn8fhT6RB8jKU1BRg==", + "version": "9.22.18", + "resolved": "https://registry.npmjs.org/@fluentui/react-provider/-/react-provider-9.22.18.tgz", + "integrity": "sha512-kLtBaw6WIzyJJCmzeublw1ifidVPnpzGS39lYjzWdO6vHwuizs5ARCgwlGXxkB+kAlG2Mma/cPFUdYOa0J2f2w==", + "license": "MIT", "dependencies": { - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-tabster": "^9.7.1", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/core": "^1.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/core": "^1.16.0", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-radio": { - "version": "9.1.13", - "resolved": "https://registry.npmjs.org/@fluentui/react-radio/-/react-radio-9.1.13.tgz", - "integrity": "sha512-5QPaI5uug2sXPe1svaAAf5nXqSyAAAIqbJsfvhzlNHMrRsvEoar9qT4HGaePGU12HuzAG7E4LXWsfKeaGZWJkw==", + "version": "9.6.4", + "resolved": "https://registry.npmjs.org/@fluentui/react-radio/-/react-radio-9.6.4.tgz", + "integrity": "sha512-punC09igeQT+3Fc67lteh4ibzi8kIAQyKJSh8gdYj9mA4WlAIAcdUIQ4cnqT57hRoz0zuUtZGXpP1y2Kbr8M+A==", + "license": "MIT", + "dependencies": { + "@fluentui/react-field": "^9.5.3", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-label": "^9.4.3", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" + } + }, + "node_modules/@fluentui/react-rating": { + "version": "9.4.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-rating/-/react-rating-9.4.3.tgz", + "integrity": "sha512-kolMzzTl9/fg54jY1iy8w54BktkKFKGLaEeiESXAbtSZiUyNIj1BADMbIG3kysbVnhkYK8Q5h0kxZPsblrL/ow==", + "license": "MIT", + "dependencies": { + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.8.0 <20.0.0", + "@types/react-dom": ">=16.8.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.8.0 <20.0.0" + } + }, + "node_modules/@fluentui/react-search": { + "version": "9.4.4", + "resolved": "https://registry.npmjs.org/@fluentui/react-search/-/react-search-9.4.4.tgz", + "integrity": "sha512-mLDqzL00XkSfJrtIZN34tQO2eBrjlPr33HuD9m3zUUQTq5g7wvA0LomT7m3RQPCJfV6FcOcMDmVfotqDUmttzA==", + "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.1.3", - "@fluentui/react-icons": "^2.0.196", - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-label": "^9.1.12", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-tabster": "^9.7.1", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-input": "^9.8.4", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0", - "scheduler": "^0.19.0 || ^0.20.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-select": { - "version": "9.1.13", - "resolved": "https://registry.npmjs.org/@fluentui/react-select/-/react-select-9.1.13.tgz", - "integrity": "sha512-gODqocFLiI8g9uYDZIy+lbH7S93Xgu13d5t9MNvcVxNw7Avob2Aa1/21a6xx95ymS9bRH9XV/ORCB1MNUysljA==", + "version": "9.5.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-select/-/react-select-9.5.3.tgz", + "integrity": "sha512-Qt4ovfXQRx11ou7OaoD0O1CNawfIzTS+Q39fX+wwLwL2yfn15oWnQGGVuQD3hWh0dh7k9cmOErRIrOKeI2wmXg==", + "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.1.3", - "@fluentui/react-icons": "^2.0.196", - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@fluentui/react-field": "^9.5.3", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-shared-contexts": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/@fluentui/react-shared-contexts/-/react-shared-contexts-9.4.0.tgz", - "integrity": "sha512-yjNvDDJAcbVcAZblh6P8xzFuwAqPcXpf9tOlsNxxlEdwlV7Bk7nDrU13wNaI+Jpks5ASNJo8zWbzUwDI1gFsdA==", + "version": "9.26.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-shared-contexts/-/react-shared-contexts-9.26.2.tgz", + "integrity": "sha512-upKXkwlIp5oIhELr4clAZXQkuCd4GDXM6GZEz8BOmRO+PnxyqmycCXvxDxsmi6XN+0vkGM4joiIgkB14o/FctQ==", + "license": "MIT", "dependencies": { - "@fluentui/react-theme": "^9.1.8", - "@swc/helpers": "^0.4.14" + "@fluentui/react-theme": "^9.2.1", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "react": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-skeleton": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-skeleton/-/react-skeleton-9.0.1.tgz", - "integrity": "sha512-1VtD8q9mnNXTAbd8873N7ISf6mrQb0QRKloGZgsoAaxnvlH6QXSR9zsigsl7utLOCQaxrns643Hmw4J10Qa06g==", + "version": "9.7.4", + "resolved": "https://registry.npmjs.org/@fluentui/react-skeleton/-/react-skeleton-9.7.4.tgz", + "integrity": "sha512-lIDvfFDldqOkmiwQU0ZEdnKnj/xxnNOGeuciuPz7ao+RyvDYf87Uo1RvTpMTveRCmpPC9z5rOX0EZZK+PhX7Dg==", + "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.1.3", - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@fluentui/react-field": "^9.5.3", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-slider": { - "version": "9.1.13", - "resolved": "https://registry.npmjs.org/@fluentui/react-slider/-/react-slider-9.1.13.tgz", - "integrity": "sha512-M9dBMo7hRVa/4k8N13IbICraNaZ0qEt4flduSX4PAlNesz6HxLD8y4vGMjQeYcufykg/BwJ93x6xr7eawOlIHQ==", + "version": "9.6.4", + "resolved": "https://registry.npmjs.org/@fluentui/react-slider/-/react-slider-9.6.4.tgz", + "integrity": "sha512-hPpbAe6pT00FG717A7wV6QCx4+WizhvT9AI/IbEifjKTQ9uxKhodDQNk8WqEXA1ziFoSifDHGAKbcOn/kdr4Ww==", + "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.1.3", - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-tabster": "^9.7.1", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@fluentui/react-field": "^9.5.3", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-spinbutton": { - "version": "9.2.13", - "resolved": "https://registry.npmjs.org/@fluentui/react-spinbutton/-/react-spinbutton-9.2.13.tgz", - "integrity": "sha512-kre/cEw6ErBawJxHopD6OVap0cE4FXCq4WInSMp4PK1R7eu2T8N35nvGk7sVR7rNIAfzhx/q7PS4JlEoZTSnwA==", + "version": "9.6.4", + "resolved": "https://registry.npmjs.org/@fluentui/react-spinbutton/-/react-spinbutton-9.6.4.tgz", + "integrity": "sha512-+t4B6anAWSXFJgmnNXOvC7S/ZWU23MOCDWrvRXKz3fki9fENN85HiRmlnx4fR8akYItVDscqQacRQRxAL8F0oA==", + "license": "MIT", "dependencies": { - "@fluentui/keyboard-keys": "^9.0.3", - "@fluentui/react-field": "^9.1.3", - "@fluentui/react-icons": "^2.0.196", - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@fluentui/keyboard-keys": "^9.0.8", + "@fluentui/react-field": "^9.5.3", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-spinner": { - "version": "9.1.12", - "resolved": "https://registry.npmjs.org/@fluentui/react-spinner/-/react-spinner-9.1.12.tgz", - "integrity": "sha512-hm2DvMJrcbhQWRUdB0Ov/eA/q8FBBs8XWR9P4APQPOftpo3Htjmx45byRJuLuu2ktosWq5JfhfXXoGi5kh5xEA==", + "version": "9.8.4", + "resolved": "https://registry.npmjs.org/@fluentui/react-spinner/-/react-spinner-9.8.4.tgz", + "integrity": "sha512-vgfsJosM6hMixFCR7mP856xKx0xXa5Vz4Y95t37Xne2yzJ47bTfqQ62kof7U1AyvaSEeDIp76cwKMyv3lQUD3A==", + "license": "MIT", + "dependencies": { + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-label": "^9.4.3", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" + } + }, + "node_modules/@fluentui/react-swatch-picker": { + "version": "9.5.4", + "resolved": "https://registry.npmjs.org/@fluentui/react-swatch-picker/-/react-swatch-picker-9.5.4.tgz", + "integrity": "sha512-UwrtK3vP2Ruo2nAI+bbu56XhtpEIwi1XvHFXpVyRWGNQI9362lMS3F4CjwDlyPR24GeF+kEgZeF7QaruTVmagQ==", + "license": "MIT", "dependencies": { - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-label": "^9.1.12", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@fluentui/react-context-selector": "^9.2.18", + "@fluentui/react-field": "^9.5.3", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.8.0 <20.0.0", + "@types/react-dom": ">=16.8.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.8.0 <20.0.0" } }, "node_modules/@fluentui/react-switch": { - "version": "9.1.13", - "resolved": "https://registry.npmjs.org/@fluentui/react-switch/-/react-switch-9.1.13.tgz", - "integrity": "sha512-MfvyyQOI4gLsT8+ktCF1qJwLGl/kD3V0CoPZMdQoEybqkW6jh8JAbX+dXzJ2JgvU0rNN4ZH+Bd+XlEb+4pEimw==", + "version": "9.7.4", + "resolved": "https://registry.npmjs.org/@fluentui/react-switch/-/react-switch-9.7.4.tgz", + "integrity": "sha512-P4Xh+zrEOXO7mUmHDPo2G/yfQYwXWArrBOBKCLKOw6qI7KjuzBJxmy1Zqm94/drRr1EKVpBaZckSiT8X8N0TNQ==", + "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.1.3", - "@fluentui/react-icons": "^2.0.196", - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-label": "^9.1.12", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-tabster": "^9.7.1", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@fluentui/react-field": "^9.5.3", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-label": "^9.4.3", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-table": { - "version": "9.2.9", - "resolved": "https://registry.npmjs.org/@fluentui/react-table/-/react-table-9.2.9.tgz", - "integrity": "sha512-thxVhW4jlfgaqPTjb6Ipn1wMQ0dDd9Bluo+tDOAf1aMBp9n3ckchpQ4qR2xwTAQ01Q771+FrrJ2nobzvNeezEg==", - "dependencies": { - "@fluentui/keyboard-keys": "^9.0.3", - "@fluentui/react-aria": "^9.3.20", - "@fluentui/react-avatar": "^9.5.1", - "@fluentui/react-checkbox": "^9.1.13", - "@fluentui/react-context-selector": "^9.1.20", - "@fluentui/react-icons": "^2.0.196", - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-radio": "^9.1.13", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-tabster": "^9.7.1", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" - }, - "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "version": "9.19.17", + "resolved": "https://registry.npmjs.org/@fluentui/react-table/-/react-table-9.19.17.tgz", + "integrity": "sha512-SPhAlS6yQ/53GB/1XUzCum63ktzmNaZVWswshr6SCo7oUERxdszr6xHJ5bSvgNczlApuLzZVz6Vnxe2s7+bsCw==", + "license": "MIT", + "dependencies": { + "@fluentui/keyboard-keys": "^9.0.8", + "@fluentui/react-aria": "^9.17.13", + "@fluentui/react-avatar": "^9.11.3", + "@fluentui/react-checkbox": "^9.6.3", + "@fluentui/react-context-selector": "^9.2.18", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-radio": "^9.6.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-tabs": { - "version": "9.3.13", - "resolved": "https://registry.npmjs.org/@fluentui/react-tabs/-/react-tabs-9.3.13.tgz", - "integrity": "sha512-m0lkRT5fEUeRDxfJElnYr7L+eQBxMMnFZXpolSV1lv9Bw2CgRamnxozhaVIoBz0RL6MebhLb6RRKgMZztVjXFQ==", + "version": "9.12.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-tabs/-/react-tabs-9.12.3.tgz", + "integrity": "sha512-CkQmrErImxvGDgrNIh+v0GbXzTKx1YSiBXYuFIhjdFaTnTk5CE79xwZp3mIkZK4SUns0HcH5wchjuO1L5LfcRg==", + "license": "MIT", "dependencies": { - "@fluentui/react-context-selector": "^9.1.20", - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-tabster": "^9.7.1", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@fluentui/react-context-selector": "^9.2.18", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0", - "scheduler": "^0.19.0 || ^0.20.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-tabster": { + "version": "9.26.16", + "resolved": "https://registry.npmjs.org/@fluentui/react-tabster/-/react-tabster-9.26.16.tgz", + "integrity": "sha512-napGx7dGdLoKoUpKlzc2Til43UMUTtr9J1GWrOFvCT6aZLTox5GjtoxQM/IPhcZ09jJOOUMbVF8ScA5u3/uyTA==", + "license": "MIT", + "dependencies": { + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1", + "keyborg": "^2.14.1", + "tabster": "^8.8.0" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" + } + }, + "node_modules/@fluentui/react-tag-picker": { + "version": "9.9.0", + "resolved": "https://registry.npmjs.org/@fluentui/react-tag-picker/-/react-tag-picker-9.9.0.tgz", + "integrity": "sha512-DYe0p4eFkCTi0HbKFWgr+MmaVhvggGnnUG4vTsgZ9zGADXPAkcVebjSGoF3LeYvRwp73t+qQRe8dT0lvBofTpw==", + "license": "MIT", + "dependencies": { + "@fluentui/keyboard-keys": "^9.0.8", + "@fluentui/react-aria": "^9.17.13", + "@fluentui/react-combobox": "^9.17.3", + "@fluentui/react-context-selector": "^9.2.18", + "@fluentui/react-field": "^9.5.3", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-portal": "^9.8.14", + "@fluentui/react-positioning": "^9.22.3", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-tags": "^9.9.2", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" + } + }, + "node_modules/@fluentui/react-tags": { + "version": "9.9.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-tags/-/react-tags-9.9.2.tgz", + "integrity": "sha512-yJmUrx3b1m4OYoXGt1+hUgZzghoTuHGGHkXyTwmCUCKX7BKAXQBbOu0VHyxmG+VDkPhpO3773ObQCFXCdTavrw==", + "license": "MIT", + "dependencies": { + "@fluentui/keyboard-keys": "^9.0.8", + "@fluentui/react-aria": "^9.17.13", + "@fluentui/react-avatar": "^9.11.3", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" + } + }, + "node_modules/@fluentui/react-teaching-popover": { "version": "9.7.1", - "resolved": "https://registry.npmjs.org/@fluentui/react-tabster/-/react-tabster-9.7.1.tgz", - "integrity": "sha512-eaB4O1fBavpL6KlYlne+J47P1Epa9kdabA5pA3iqa4dKqCrWOMAqY2rZVb7hR6zr0o7n2MCEaHCQFOJymsyafQ==", + "resolved": "https://registry.npmjs.org/@fluentui/react-teaching-popover/-/react-teaching-popover-9.7.1.tgz", + "integrity": "sha512-YZ/bZtrFhMowFJYqHq9Yr73PldoFjwf/7sjv5MiBx8SNl+0S+DhQndnsv3iv2A+XQPg9lI/RzYLRQ4PGJwvDYQ==", + "license": "MIT", "dependencies": { - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14", - "keyborg": "^2.0.0", - "tabster": "^4.1.1" + "@fluentui/react-aria": "^9.17.13", + "@fluentui/react-button": "^9.10.0", + "@fluentui/react-context-selector": "^9.2.18", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-popover": "^9.14.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1", + "use-sync-external-store": "^1.2.0" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.8.0 <20.0.0", + "@types/react-dom": ">=16.8.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.8.0 <20.0.0" } }, "node_modules/@fluentui/react-text": { - "version": "9.3.9", - "resolved": "https://registry.npmjs.org/@fluentui/react-text/-/react-text-9.3.9.tgz", - "integrity": "sha512-IPrxF2YmS6Nf7aa3ochgki+m7CBkwT6NcmJtZpg0oPz2k24V3g6d8VqXIIQkU0HmR/fNU5YJnmRj+ewy3d2t8A==", + "version": "9.6.18", + "resolved": "https://registry.npmjs.org/@fluentui/react-text/-/react-text-9.6.18.tgz", + "integrity": "sha512-iED0KJPtU44M5kByfg93n/Zwwky0BhyRHaWFcIeB6jsCVAeCf8kUSS2Nr+7zQocf60DFHgMF7y4XEl0rRe+PHw==", + "license": "MIT", "dependencies": { - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-textarea": { - "version": "9.3.13", - "resolved": "https://registry.npmjs.org/@fluentui/react-textarea/-/react-textarea-9.3.13.tgz", - "integrity": "sha512-+y2XsB9cTy07GSeVp418PvC9KgOQadbsoKACy4hCQNuyYG22rG9JfjOngvhFLGyfty8az1XUtDFoOBN0KFrdZQ==", + "version": "9.7.4", + "resolved": "https://registry.npmjs.org/@fluentui/react-textarea/-/react-textarea-9.7.4.tgz", + "integrity": "sha512-Zq2D8u2ssneLVY4OuvMWYT5Er3yAo3OKmTWmPNsJ6F9dISIc7UullDwuBoKYES943EBzSfNyKZQwCY7Bo1BGuQ==", + "license": "MIT", "dependencies": { - "@fluentui/react-field": "^9.1.3", - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@fluentui/react-field": "^9.5.3", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-theme": { - "version": "9.1.8", - "resolved": "https://registry.npmjs.org/@fluentui/react-theme/-/react-theme-9.1.8.tgz", - "integrity": "sha512-KXSPSfg29sHEHw9rFpZjKTU4KwY4F4kxZIcqA83Kz8Khnfw17NiWmz8XcmxXaMUlqfwVRxBIM9um2uFE5gjcpw==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@fluentui/react-theme/-/react-theme-9.2.1.tgz", + "integrity": "sha512-lJxfz7LmmglFz+c9C41qmMqaRRZZUPtPPl9DWQ79vH+JwZd4dkN7eA78OTRwcGCOTPEKoLTX72R+EFaWEDlX+w==", + "license": "MIT", + "dependencies": { + "@fluentui/tokens": "1.0.0-alpha.23", + "@swc/helpers": "^0.5.1" + } + }, + "node_modules/@fluentui/react-toast": { + "version": "9.8.1", + "resolved": "https://registry.npmjs.org/@fluentui/react-toast/-/react-toast-9.8.1.tgz", + "integrity": "sha512-J9nKVwbwmBxDNrArgJ9GHypWH43WW0XJhNWvC6ED4dGrvgc8Rnw7bKxI7swG46OTMJNCkwrOnGNEu5YGkMigfw==", + "license": "MIT", "dependencies": { - "@fluentui/tokens": "1.0.0-alpha.5", - "@swc/helpers": "^0.4.14" + "@fluentui/keyboard-keys": "^9.0.8", + "@fluentui/react-aria": "^9.17.13", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-motion": "^9.16.1", + "@fluentui/react-motion-components-preview": "^0.15.6", + "@fluentui/react-portal": "^9.8.14", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-toolbar": { - "version": "9.1.13", - "resolved": "https://registry.npmjs.org/@fluentui/react-toolbar/-/react-toolbar-9.1.13.tgz", - "integrity": "sha512-TEwnFGbrfJqg554AHTfcUCfufEuBWMvRWzUYoBSva/dGVanqRYolht3Dq+JmE+6EmmWKCfVh29excMoCUHWh3A==", + "version": "9.8.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-toolbar/-/react-toolbar-9.8.2.tgz", + "integrity": "sha512-jTy8bRYYV//5z0VSWWAUNozr8woBLNsKQGTLsbtSeyOnAXLfSlULSrLC2c5yIkgairFE3K+ybv8o4R+HgCbKTQ==", + "license": "MIT", "dependencies": { - "@fluentui/react-button": "^9.3.12", - "@fluentui/react-context-selector": "^9.1.20", - "@fluentui/react-divider": "^9.2.12", - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-radio": "^9.1.13", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-tabster": "^9.7.1", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@fluentui/react-button": "^9.10.0", + "@fluentui/react-context-selector": "^9.2.18", + "@fluentui/react-divider": "^9.7.3", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-radio": "^9.6.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-tooltip": { - "version": "9.2.12", - "resolved": "https://registry.npmjs.org/@fluentui/react-tooltip/-/react-tooltip-9.2.12.tgz", - "integrity": "sha512-hl+e3yb6q1Rb53+bCFbZvaNxPFOKBE/aoZpRORwtk+62XvYEdLpP8gE1d+djdIyYufN/jMCoQehsNmOCv00+kg==", + "version": "9.10.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-tooltip/-/react-tooltip-9.10.3.tgz", + "integrity": "sha512-QDc5XQyODm0BIQ5VCbM59n0pEXNCMk2a9OQ7B5eDWoqnvTxj++ul1XQb6EF0libbkjFl7zTsaaHnhIOzsVEq0w==", + "license": "MIT", "dependencies": { - "@fluentui/keyboard-keys": "^9.0.3", - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-portal": "^9.2.8", - "@fluentui/react-positioning": "^9.5.12", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@fluentui/keyboard-keys": "^9.0.8", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-portal": "^9.8.14", + "@fluentui/react-positioning": "^9.22.3", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-tree": { - "version": "9.0.0-beta.14", - "resolved": "https://registry.npmjs.org/@fluentui/react-tree/-/react-tree-9.0.0-beta.14.tgz", - "integrity": "sha512-2WMJmsyHKaXY7fePPGy479Y8k/fCf1tdC8KO680XqtFPNb78xSvHkfLI0T2wngMNcF6d7qyDQqtbIlv5lQQESQ==", - "dependencies": { - "@fluentui/keyboard-keys": "^9.0.3", - "@fluentui/react-aria": "^9.3.20", - "@fluentui/react-avatar": "^9.5.1", - "@fluentui/react-button": "^9.3.12", - "@fluentui/react-context-selector": "^9.1.20", - "@fluentui/react-icons": "^2.0.196", - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-portal": "^9.2.8", - "@fluentui/react-shared-contexts": "^9.4.0", - "@fluentui/react-tabster": "^9.7.1", - "@fluentui/react-theme": "^9.1.8", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" - }, - "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "version": "9.16.2", + "resolved": "https://registry.npmjs.org/@fluentui/react-tree/-/react-tree-9.16.2.tgz", + "integrity": "sha512-q2W8zt760m7LSkkcSbzFgULi0hykFYNFqVJsM1WGbsCNOgsjNZt7foIt1jFM6jliIohJy6Bh3XahLnaaSlDqjQ==", + "license": "MIT", + "dependencies": { + "@fluentui/keyboard-keys": "^9.0.8", + "@fluentui/react-aria": "^9.17.13", + "@fluentui/react-avatar": "^9.11.3", + "@fluentui/react-button": "^9.10.0", + "@fluentui/react-checkbox": "^9.6.3", + "@fluentui/react-context-selector": "^9.2.18", + "@fluentui/react-icons": "^2.0.245", + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-motion": "^9.16.1", + "@fluentui/react-motion-components-preview": "^0.15.6", + "@fluentui/react-radio": "^9.6.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-tabster": "^9.26.16", + "@fluentui/react-theme": "^9.2.1", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" + }, + "peerDependencies": { + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-utilities": { - "version": "9.9.0", - "resolved": "https://registry.npmjs.org/@fluentui/react-utilities/-/react-utilities-9.9.0.tgz", - "integrity": "sha512-PJRISHpB/cZLWl1Ii+e0G6FJ/qqO71hjC7wO+t/QbL8o4rB/8yL9BwMM62mx5hWrnQygcEf2NeZWMAoZxnhIGQ==", + "version": "9.26.5", + "resolved": "https://registry.npmjs.org/@fluentui/react-utilities/-/react-utilities-9.26.5.tgz", + "integrity": "sha512-lLWhnfMVEu+cWx3o9uTA5sDwo4U9PnpDJGVtheZ1bOCdh1YiQsJxeFM7n6nLE72UK2w+ATkGZQPYZA4QW1JLPQ==", + "license": "MIT", "dependencies": { - "@fluentui/keyboard-keys": "^9.0.3", - "@swc/helpers": "^0.4.14" + "@fluentui/keyboard-keys": "^9.0.8", + "@fluentui/react-shared-contexts": "^9.26.2", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "react": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/react-virtualizer": { - "version": "9.0.0-alpha.20", - "resolved": "https://registry.npmjs.org/@fluentui/react-virtualizer/-/react-virtualizer-9.0.0-alpha.20.tgz", - "integrity": "sha512-tJblL2ccU2FJLZzp641ZiW1CUZH880hZFkij/Pxz34sKXpEskpgoJF4Z93V2STpP+9128DIkrp106mn6fVxbMA==", + "version": "9.0.0-alpha.114", + "resolved": "https://registry.npmjs.org/@fluentui/react-virtualizer/-/react-virtualizer-9.0.0-alpha.114.tgz", + "integrity": "sha512-hD44CrZh84P1Rsd+ACPdmre3j20OevkoMKxMRzMXWlSIYKbT+m5I5yM3XxxSvKb1Qr77LeBPTTJs6apvMcfRiA==", + "license": "MIT", "dependencies": { - "@fluentui/react-jsx-runtime": "9.0.0-alpha.4", - "@fluentui/react-utilities": "^9.9.0", - "@griffel/react": "^1.5.2", - "@swc/helpers": "^0.4.14" + "@fluentui/react-jsx-runtime": "^9.4.4", + "@fluentui/react-shared-contexts": "^9.26.2", + "@fluentui/react-utilities": "^9.26.5", + "@griffel/react": "^1.5.32", + "@swc/helpers": "^0.5.1" }, "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "@types/react": ">=16.14.0 <20.0.0", + "@types/react-dom": ">=16.9.0 <20.0.0", + "react": ">=16.14.0 <20.0.0", + "react-dom": ">=16.14.0 <20.0.0" } }, "node_modules/@fluentui/tokens": { - "version": "1.0.0-alpha.5", - "resolved": "https://registry.npmjs.org/@fluentui/tokens/-/tokens-1.0.0-alpha.5.tgz", - "integrity": "sha512-4xCNP/tmeDywmo+PoFqDaUADSvNNzoZHVknC4D77S1RWxVuYmcM15eumKcVRrDuW3wS8eEX4/ZsIlDfqAhnU8g==", + "version": "1.0.0-alpha.23", + "resolved": "https://registry.npmjs.org/@fluentui/tokens/-/tokens-1.0.0-alpha.23.tgz", + "integrity": "sha512-uxrzF9Z+J10naP0pGS7zPmzSkspSS+3OJDmYIK3o1nkntQrgBXq3dBob4xSlTDm5aOQ0kw6EvB9wQgtlyy4eKQ==", + "license": "MIT", "dependencies": { - "@swc/helpers": "^0.4.14" + "@swc/helpers": "^0.5.1" } }, - "node_modules/@fluidframework/aqueduct": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/aqueduct/-/aqueduct-1.3.6.tgz", - "integrity": "sha512-33vWqX1UEwYYTHb3Iv6+1B4ZFFcPNdD3cqfAmYbR7nOwxPYq1uKflUzafUOKW6SMpRyomeebCy/f5/PIoG+yJA==", - "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/container-definitions": "^1.3.6", - "@fluidframework/container-loader": "^1.3.6", - "@fluidframework/container-runtime": "^1.3.6", - "@fluidframework/container-runtime-definitions": "^1.3.6", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/datastore": "^1.3.6", - "@fluidframework/datastore-definitions": "^1.3.6", - "@fluidframework/map": "^1.3.6", - "@fluidframework/request-handler": "^1.3.6", - "@fluidframework/runtime-definitions": "^1.3.6", - "@fluidframework/runtime-utils": "^1.3.6", - "@fluidframework/synthesize": "^1.3.6", - "@fluidframework/view-interfaces": "^1.3.6", - "uuid": "^8.3.1" - } - }, - "node_modules/@fluidframework/aqueduct/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" + "node_modules/@fluid-experimental/attributor": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluid-experimental/attributor/-/attributor-2.110.0.tgz", + "integrity": "sha512-lxBIX7j8rkRKQW1QxjBSJnN3nZeR9w6oFwAU2EC5Bi8j2eH/efD1GDyxXAmWdR7BnWubp6ukRea/d3DP85Xyzg==", + "license": "MIT", + "dependencies": { + "@fluid-internal/client-utils": "~2.110.0", + "@fluidframework/container-definitions": "~2.110.0", + "@fluidframework/container-runtime": "~2.110.0", + "@fluidframework/container-runtime-definitions": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/datastore": "~2.110.0", + "@fluidframework/datastore-definitions": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "@fluidframework/runtime-definitions": "~2.110.0", + "@fluidframework/runtime-utils": "~2.110.0", + "@fluidframework/telemetry-utils": "~2.110.0", + "lz4js": "^0.2.0" + } + }, + "node_modules/@fluid-experimental/sequence-deprecated": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluid-experimental/sequence-deprecated/-/sequence-deprecated-2.110.0.tgz", + "integrity": "sha512-ay0WfIYksi/oXe02Jt41nNaCGy3m9O7u4SmJppvbX44ZfjGAwzSCtcmZ7/nKaZB3Qoh6xzPl373+iGaMr2cYNg==", + "license": "MIT", + "dependencies": { + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/datastore-definitions": "~2.110.0", + "@fluidframework/merge-tree": "~2.110.0", + "@fluidframework/sequence": "~2.110.0", + "@fluidframework/shared-object-base": "~2.110.0" } }, - "node_modules/@fluidframework/azure-client": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@fluidframework/azure-client/-/azure-client-1.1.1.tgz", - "integrity": "sha512-2raaGv2nWxdMbcrw9kuDhHd8coqqVloIoM7X19NmcCVP7FLkT7n8Fj2O/7gg8ccqsaMSXNWCRhbtMpca/lcD8g==", - "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/common-utils": "^1.0.0", - "@fluidframework/container-definitions": "^1.3.3", - "@fluidframework/container-loader": "^1.3.3", - "@fluidframework/core-interfaces": "^1.3.3", - "@fluidframework/driver-definitions": "^1.3.3", - "@fluidframework/driver-utils": "^1.3.3", - "@fluidframework/fluid-static": "^1.3.3", - "@fluidframework/map": "^1.3.3", - "@fluidframework/protocol-definitions": "^1.0.0", - "@fluidframework/routerlicious-driver": "^1.3.3", - "@fluidframework/runtime-utils": "^1.3.3", - "@fluidframework/server-services-client": "^0.1036.5001", - "axios": "^0.21.2", - "uuid": "^8.3.1" - }, - "peerDependencies": { - "fluid-framework": "^1.3.3" - } - }, - "node_modules/@fluidframework/azure-client/node_modules/@fluidframework/common-utils": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@fluidframework/common-utils/-/common-utils-1.1.1.tgz", - "integrity": "sha512-XCPEFE1JAg+juQZYQQVZjHZJlM5+Wm9NxRbsnsix05M1tSq0p3SLqwgfaSGssXhLLX5QtG+aF1QD5a3LA1qtNQ==", + "node_modules/@fluid-internal/client-utils": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluid-internal/client-utils/-/client-utils-2.110.0.tgz", + "integrity": "sha512-g2q6/0UPVdKQvhVYDzTEd8A5+Jyt+VpmCKJxS7cqns+TvMmCdi4WnzeGH8Fn7beGkpdV5jHEoe8fpXFOwKcfOg==", + "license": "MIT", "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@types/events": "^3.0.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@types/events_pkg": "npm:@types/events@^3.0.0", "base64-js": "^1.5.1", "buffer": "^6.0.3", - "events": "^3.1.0", - "lodash": "^4.17.21", - "sha.js": "^2.4.11" + "events_pkg": "npm:events@^3.1.0", + "sha.js": "^2.4.12" } }, - "node_modules/@fluidframework/azure-client/node_modules/@fluidframework/protocol-definitions": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@fluidframework/protocol-definitions/-/protocol-definitions-1.2.0.tgz", - "integrity": "sha512-2/GoupA8mjHD8gcjyn4SedqJStKlQAZxga5PtDBoh+xHsuugQRhsAHJCX+8tdqbSK4ZOo9z8iq/vWKVLUi5Dzw==", + "node_modules/@fluid-internal/eslint-plugin-fluid": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@fluid-internal/eslint-plugin-fluid/-/eslint-plugin-fluid-0.4.1.tgz", + "integrity": "sha512-JTFmMtNDJ+pR0Z0jvreXgq2GymqcCSD0InclRQfimEJ4KzIwdHCPHCmODlll1FG/Qp852baMYgdKHHD4qqRP/w==", + "dev": true, + "license": "MIT", "dependencies": { - "@fluidframework/common-definitions": "^0.20.1" + "@microsoft/tsdoc": "^0.15.1", + "@typescript-eslint/parser": "~8.46.0", + "@typescript-eslint/utils": "~8.46.0", + "ts-morph": "^22.0.0" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.37.0" } }, - "node_modules/@fluidframework/azure-client/node_modules/axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "node_modules/@fluid-internal/eslint-plugin-fluid/node_modules/@typescript-eslint/parser": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.4.tgz", + "integrity": "sha512-tK3GPFWbirvNgsNKto+UmB/cRtn6TZfyw0D6IKrW55n6Vbs7KJoZtI//kpTKzE/DUmmnAFD8/Ca46s7Obs92/w==", + "dev": true, + "license": "MIT", "dependencies": { - "follow-redirects": "^1.14.0" - } - }, - "node_modules/@fluidframework/azure-client/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" + "@typescript-eslint/scope-manager": "8.46.4", + "@typescript-eslint/types": "8.46.4", + "@typescript-eslint/typescript-estree": "8.46.4", + "@typescript-eslint/visitor-keys": "8.46.4", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@fluidframework/cell": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/cell/-/cell-1.3.6.tgz", - "integrity": "sha512-H2SClm04fokJcfLVPtqNKnhEb986gKEPyHA/K2I4IRxRk3kcF327vV/0hpD/A22DDsrAMghTcYDTSXzd/ZUaag==", + "node_modules/@fluid-internal/eslint-plugin-fluid/node_modules/@typescript-eslint/scope-manager": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.4.tgz", + "integrity": "sha512-tMDbLGXb1wC+McN1M6QeDx7P7c0UWO5z9CXqp7J8E+xGcJuUuevWKxuG8j41FoweS3+L41SkyKKkia16jpX7CA==", "dev": true, + "license": "MIT", "dependencies": { - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/datastore-definitions": "^1.3.6", - "@fluidframework/driver-utils": "^1.3.6", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/runtime-definitions": "^1.3.6", - "@fluidframework/shared-object-base": "^1.3.6" + "@typescript-eslint/types": "8.46.4", + "@typescript-eslint/visitor-keys": "8.46.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@fluidframework/common-definitions": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@fluidframework/common-definitions/-/common-definitions-0.20.1.tgz", - "integrity": "sha512-KaoQ7w2MDH5OeRKVatL5yVOCFg+9wD6bLSLFh1/TV1EZM46l49iBqO7UVjUtPE6BIm0jvvOzJXULGVSpzokX3g==" - }, - "node_modules/@fluidframework/common-utils": { - "version": "0.32.2", - "resolved": "https://registry.npmjs.org/@fluidframework/common-utils/-/common-utils-0.32.2.tgz", - "integrity": "sha512-PoGX7/l0vWKt5JaAxcgFOdGje30Q6qSE06YzFIKh9Ba3oq7B60+TFqu7c2ErQt6sNddmvcAcAiLVNaTGAip3vw==", - "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@types/events": "^3.0.0", - "base64-js": "^1.5.1", - "buffer": "^6.0.3", - "events": "^3.1.0", - "lodash": "^4.17.21", - "sha.js": "^2.4.11" + "node_modules/@fluid-internal/eslint-plugin-fluid/node_modules/@typescript-eslint/types": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.4.tgz", + "integrity": "sha512-USjyxm3gQEePdUwJBFjjGNG18xY9A2grDVGuk7/9AkjIF1L+ZrVnwR5VAU5JXtUnBL/Nwt3H31KlRDaksnM7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@fluidframework/container-definitions": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/container-definitions/-/container-definitions-1.3.6.tgz", - "integrity": "sha512-+5fuIUG7jGjKrRHtrH2VgrRI0YUXcP9jSLrHdI4Ks+4kNSDiOlu+UT7j9T9KoBAfHOpnihS3PVeDBJtIeqgDZw==", + "node_modules/@fluid-internal/eslint-plugin-fluid/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.4.tgz", + "integrity": "sha512-7oV2qEOr1d4NWNmpXLR35LvCfOkTNymY9oyW+lUHkmCno7aOmIf/hMaydnJBUTBMRCOGZh8YjkFOc8dadEoNGA==", + "dev": true, + "license": "MIT", "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/driver-definitions": "^1.3.6", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "events": "^3.1.0" - } - }, - "node_modules/@fluidframework/container-loader": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/container-loader/-/container-loader-1.3.6.tgz", - "integrity": "sha512-J7nF7XTHCtL24gGnUhg155kolokX8HRWJqj2XEjaPrBsRmkyiySP+qCnrKY0bgLqaFLHW4WYfmC80lFE3oaELg==", - "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/container-definitions": "^1.3.6", - "@fluidframework/container-utils": "^1.3.6", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/driver-definitions": "^1.3.6", - "@fluidframework/driver-utils": "^1.3.6", - "@fluidframework/protocol-base": "^0.1036.5001", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/telemetry-utils": "^1.3.6", - "abort-controller": "^3.0.0", - "double-ended-queue": "^2.1.0-0", - "events": "^3.1.0", - "lodash": "^4.17.21", - "url": "^0.11.0", - "uuid": "^8.3.1" + "@typescript-eslint/project-service": "8.46.4", + "@typescript-eslint/tsconfig-utils": "8.46.4", + "@typescript-eslint/types": "8.46.4", + "@typescript-eslint/visitor-keys": "8.46.4", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@fluidframework/container-loader/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" + "node_modules/@fluid-internal/eslint-plugin-fluid/node_modules/@typescript-eslint/utils": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.4.tgz", + "integrity": "sha512-AbSv11fklGXV6T28dp2Me04Uw90R2iJ30g2bgLz529Koehrmkbs1r7paFqr1vPCZi7hHwYxYtxfyQMRC8QaVSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.46.4", + "@typescript-eslint/types": "8.46.4", + "@typescript-eslint/typescript-estree": "8.46.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@fluidframework/container-runtime": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/container-runtime/-/container-runtime-1.3.6.tgz", - "integrity": "sha512-YC1Bvd8UiO3YID/sU9yxMMibW0FPqpf+sS47Czg1ILf2twK48U2BopDDKNeIHJFDl3yNOqxJniUkJJLNoYWwqg==", - "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/container-definitions": "^1.3.6", - "@fluidframework/container-runtime-definitions": "^1.3.6", - "@fluidframework/container-utils": "^1.3.6", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/datastore": "^1.3.6", - "@fluidframework/driver-definitions": "^1.3.6", - "@fluidframework/driver-utils": "^1.3.6", - "@fluidframework/garbage-collector": "^1.3.6", - "@fluidframework/protocol-base": "^0.1036.5001", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/runtime-definitions": "^1.3.6", - "@fluidframework/runtime-utils": "^1.3.6", - "@fluidframework/telemetry-utils": "^1.3.6", - "double-ended-queue": "^2.1.0-0", - "events": "^3.1.0", - "uuid": "^8.3.1" + "node_modules/@fluid-internal/eslint-plugin-fluid/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.4.tgz", + "integrity": "sha512-/++5CYLQqsO9HFGLI7APrxBJYo+5OCMpViuhV8q5/Qa3o5mMrF//eQHks+PXcsAVaLdn817fMuS7zqoXNNZGaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.46.4", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@fluidframework/container-runtime-definitions": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/container-runtime-definitions/-/container-runtime-definitions-1.3.6.tgz", - "integrity": "sha512-cQP/F2F9BjeXKyUNmwQCRRb5qJPoufZ/iIyBSdj8qEYwhTyv3Ogbk+LyHz5cG8wPYlM2ff8IirxwEdgq7VTL/w==", - "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/container-definitions": "^1.3.6", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/driver-definitions": "^1.3.6", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/runtime-definitions": "^1.3.6" + "node_modules/@fluid-internal/eslint-plugin-fluid/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@fluidframework/container-runtime/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" + "node_modules/@fluid-internal/eslint-plugin-fluid/node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" } }, - "node_modules/@fluidframework/container-utils": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/container-utils/-/container-utils-1.3.6.tgz", - "integrity": "sha512-Hf3kxHuRzQv3a7J+I/3q5OH3WW5lajy3ENucc1HLCuOKYi39MM5AfAMBEfaTl1aI5iMxhHEyDAZJhaGJvvgOew==", + "node_modules/@fluid-internal/presence-definitions": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluid-internal/presence-definitions/-/presence-definitions-2.110.0.tgz", + "integrity": "sha512-xvw+uTD2VsIb4FgaQt3dot8RyFZcCVpwDV9WifQXGf58BAX4/En4Vw2jiras/j5RZ0dAEFHDIBqV+JOlevLEJw==", + "license": "MIT", "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/container-definitions": "^1.3.6", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/telemetry-utils": "^1.3.6" + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/id-compressor": "~2.110.0" } }, - "node_modules/@fluidframework/core-interfaces": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/core-interfaces/-/core-interfaces-1.3.6.tgz", - "integrity": "sha512-6ccflpLJvlPhZ58MiMUUC5XvWF1s5yTmP3dXHsJf514IzuAvS5PCGLdZWUjWCgxA2fPvZKzA4VfWpwyFt1H0LA==" + "node_modules/@fluid-internal/presence-runtime": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluid-internal/presence-runtime/-/presence-runtime-2.110.0.tgz", + "integrity": "sha512-mzMpJHq1TiQOcF5hsRYjed5oRd6LbvfNRfPOImobKdFNeR5U02utN7JD47ZweBv/+xzJxCBqHDpi8p5JSMb5og==", + "license": "MIT", + "dependencies": { + "@fluid-internal/client-utils": "~2.110.0", + "@fluid-internal/presence-definitions": "~2.110.0", + "@fluidframework/container-definitions": "~2.110.0", + "@fluidframework/container-runtime-definitions": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/id-compressor": "~2.110.0", + "@fluidframework/runtime-definitions": "~2.110.0", + "@fluidframework/telemetry-utils": "~2.110.0" + } + }, + "node_modules/@fluid-internal/test-driver-definitions": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluid-internal/test-driver-definitions/-/test-driver-definitions-2.110.0.tgz", + "integrity": "sha512-kIHHGnZTGyCcxQASX0A+z/3Oo1F72lMbiOg5Xj/Jlg2JXT7pON9OrSwJWniaUoMWPqTYuPz9kUwUOCahfQyXuA==", + "license": "MIT", + "dependencies": { + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0" + } }, - "node_modules/@fluidframework/counter": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/counter/-/counter-1.3.6.tgz", - "integrity": "sha512-nKruUnkmrHxlwOINXQPxFrjjjCTE1BkLRGQLQY1v46IkACvl9zbj+mYJzF4BSfjzkBpR4KBS0Delc7jR0AcT+A==", - "dev": true, + "node_modules/@fluidframework/agent-scheduler": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/agent-scheduler/-/agent-scheduler-2.110.0.tgz", + "integrity": "sha512-2sGEO1a3HiLhoTmmmUKgmaWhmpD7VTMsqfSV2US5NJo+BH6vCFfLk5YkU9cfCcmsqbNLlzS6HVLpqdClqQGrew==", + "license": "MIT", "dependencies": { - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/datastore-definitions": "^1.3.6", - "@fluidframework/driver-utils": "^1.3.6", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/runtime-definitions": "^1.3.6", - "@fluidframework/shared-object-base": "^1.3.6" + "@fluid-internal/client-utils": "~2.110.0", + "@fluidframework/container-definitions": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/datastore": "~2.110.0", + "@fluidframework/datastore-definitions": "~2.110.0", + "@fluidframework/map": "~2.110.0", + "@fluidframework/register-collection": "~2.110.0", + "@fluidframework/runtime-definitions": "~2.110.0", + "@fluidframework/runtime-utils": "~2.110.0", + "@fluidframework/telemetry-utils": "~2.110.0", + "uuid": "^11.1.0" + } + }, + "node_modules/@fluidframework/agent-scheduler/node_modules/uuid": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" } }, - "node_modules/@fluidframework/datastore": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/datastore/-/datastore-1.3.6.tgz", - "integrity": "sha512-eQTkB/Z0Sn5JwZ66EvY3r4RflSoZth0Zi7ezD4kbx75c4wmixRSs+qGSMM0xbllFXjyA24ucbL21zduVLxZGcg==", - "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/container-definitions": "^1.3.6", - "@fluidframework/container-utils": "^1.3.6", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/datastore-definitions": "^1.3.6", - "@fluidframework/driver-definitions": "^1.3.6", - "@fluidframework/driver-utils": "^1.3.6", - "@fluidframework/garbage-collector": "^1.3.6", - "@fluidframework/protocol-base": "^0.1036.5001", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/runtime-definitions": "^1.3.6", - "@fluidframework/runtime-utils": "^1.3.6", - "@fluidframework/telemetry-utils": "^1.3.6", - "lodash": "^4.17.21", - "uuid": "^8.3.1" + "node_modules/@fluidframework/aqueduct": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/aqueduct/-/aqueduct-2.110.0.tgz", + "integrity": "sha512-jRdP0DK/tkghSa2KLlIn4yJIQAFL9kFRdwBvCoJqfeN39vi/tOo9estLGVNwxU8Jna7TvZ0LfHMRn+sffzdgIg==", + "license": "MIT", + "dependencies": { + "@fluid-internal/client-utils": "~2.110.0", + "@fluidframework/container-definitions": "~2.110.0", + "@fluidframework/container-runtime": "~2.110.0", + "@fluidframework/container-runtime-definitions": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/datastore": "~2.110.0", + "@fluidframework/datastore-definitions": "~2.110.0", + "@fluidframework/map": "~2.110.0", + "@fluidframework/request-handler": "~2.110.0", + "@fluidframework/runtime-definitions": "~2.110.0", + "@fluidframework/runtime-utils": "~2.110.0", + "@fluidframework/shared-object-base": "~2.110.0", + "@fluidframework/synthesize": "~2.110.0", + "@fluidframework/telemetry-utils": "~2.110.0", + "@fluidframework/tree": "~2.110.0" } }, - "node_modules/@fluidframework/datastore-definitions": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/datastore-definitions/-/datastore-definitions-1.3.6.tgz", - "integrity": "sha512-9kgqa5FsIHHuxQPL50cm/FX6FOukBDDHG45ByGEChISbnfkS13xncLrY6mE4FgTC1jW0d7y3CgGT3pn4n9Hc+g==", + "node_modules/@fluidframework/azure-client": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/azure-client/-/azure-client-2.110.0.tgz", + "integrity": "sha512-Ra6ZiY/rhAwGAWcbbAARFlGbkd8o7ZtvVulSmpiPTixYyvO8i8jzBYZRijphEyVARq2EUp6kOedab8pNJWePbg==", + "license": "MIT", "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/container-definitions": "^1.3.6", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/runtime-definitions": "^1.3.6" + "@fluidframework/container-definitions": "~2.110.0", + "@fluidframework/container-loader": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "@fluidframework/driver-utils": "~2.110.0", + "@fluidframework/fluid-static": "~2.110.0", + "@fluidframework/routerlicious-driver": "~2.110.0", + "@fluidframework/runtime-definitions": "~2.110.0", + "@fluidframework/telemetry-utils": "~2.110.0" } }, - "node_modules/@fluidframework/datastore/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" + "node_modules/@fluidframework/cell": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/cell/-/cell-2.110.0.tgz", + "integrity": "sha512-V3wvwillWqGtGYdARjvXwGvFdNH61BtffMRxqEiE2NISwj/9QJSScbWxy8xyqSzghhmOIOG7MGdB0+BleLM49A==", + "license": "MIT", + "dependencies": { + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/datastore-definitions": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "@fluidframework/driver-utils": "~2.110.0", + "@fluidframework/runtime-definitions": "~2.110.0", + "@fluidframework/shared-object-base": "~2.110.0" } }, - "node_modules/@fluidframework/driver-base": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/driver-base/-/driver-base-1.3.6.tgz", - "integrity": "sha512-Ini7PyyIP+out9+5eAqq+QYWfxSGprVtxTrtipmoKCjI6XTmgfmSwrs9VPrgdIl6lI52RjEFWQtC/J3vmjAesg==", + "node_modules/@fluidframework/common-definitions": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@fluidframework/common-definitions/-/common-definitions-1.1.0.tgz", + "integrity": "sha512-WQYtG9tkx2j7i1JSXPvwLnQsqCOZAghMj0aGciqjZVNppUly/XBpAjb4V6FEUCEjxCScPKhyE+1rhV1ep52NgA==", + "license": "MIT" + }, + "node_modules/@fluidframework/common-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@fluidframework/common-utils/-/common-utils-3.1.0.tgz", + "integrity": "sha512-KpBQqpZKAHCKFMoxtAdrgqL1nIJhT7r2IRGmS3Rm5CMTLsegQ8ifX5lFvd6IbjeWmvLz1qLsY3eS5HBYqy9CVQ==", + "license": "MIT", "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/driver-definitions": "^1.3.6", - "@fluidframework/driver-utils": "^1.3.6", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/telemetry-utils": "^1.3.6" + "@fluidframework/common-definitions": "^1.1.0", + "@types/events": "^3.0.0", + "base64-js": "^1.5.1", + "buffer": "^6.0.3", + "events": "^3.1.0", + "lodash": "^4.17.21", + "sha.js": "^2.4.11" } }, - "node_modules/@fluidframework/driver-definitions": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/driver-definitions/-/driver-definitions-1.3.6.tgz", - "integrity": "sha512-5Rvk2NhXxh2bhk8WWnBtcJq/9TgVYhAj4z7DDuqXqJyRUF/XYhyxqOfMuo7IAhTa2oTpp8o7QDwZqsfWKfC9tA==", + "node_modules/@fluidframework/container-definitions": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/container-definitions/-/container-definitions-2.110.0.tgz", + "integrity": "sha512-FeXGQ2WU4HwchP3UTVpEeCXREAJccS2/Iv5Vcntm1hMaGRjdmtAPk5uNicGmf6i4/PUHmO2jrMtJhkVMmie5bg==", + "license": "MIT", "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/protocol-definitions": "^0.1028.2000" + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0" } }, - "node_modules/@fluidframework/driver-utils": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/driver-utils/-/driver-utils-1.3.6.tgz", - "integrity": "sha512-yDbuR4eMj0Y+kbIwV0XaXd3kh+U1YxmU1Qgcxa2RgD3MEMsDiCBaQrUCPjjxmBT9diUfBijVxjjOc5vUfm/eBA==", + "node_modules/@fluidframework/container-loader": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/container-loader/-/container-loader-2.110.0.tgz", + "integrity": "sha512-W1wNWntdV2OiJGIIEphRZoKnPWW/1Ag0t5iR+XpxOsNKF4i7tHbeBH8Fzg3ZpvDdVEwkZcsNWWVrvuw1UvYXRw==", + "license": "MIT", "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/driver-definitions": "^1.3.6", - "@fluidframework/gitresources": "^0.1036.5001", - "@fluidframework/protocol-base": "^0.1036.5001", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/telemetry-utils": "^1.3.6", - "axios": "^0.26.0", - "uuid": "^8.3.1" + "@fluid-internal/client-utils": "~2.110.0", + "@fluidframework/container-definitions": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "@fluidframework/driver-utils": "~2.110.0", + "@fluidframework/telemetry-utils": "~2.110.0", + "debug": "^4.3.4", + "double-ended-queue": "^2.1.0-0", + "events_pkg": "npm:events@^3.1.0", + "uuid": "^11.1.0" } }, - "node_modules/@fluidframework/driver-utils/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "node_modules/@fluidframework/container-loader/node_modules/uuid": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" + "uuid": "dist/esm/bin/uuid" } }, - "node_modules/@fluidframework/fluid-static": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/fluid-static/-/fluid-static-1.3.6.tgz", - "integrity": "sha512-ncGgaDmewFQJou9roh+8K94hhpIlNEGvLaxNnofgFHAq1R2vLlx+zb5VGMMywnof+gvjgrsk4JOP2C9XpMs9Tw==", - "dependencies": { - "@fluidframework/aqueduct": "^1.3.6", - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/container-definitions": "^1.3.6", - "@fluidframework/container-loader": "^1.3.6", - "@fluidframework/container-runtime-definitions": "^1.3.6", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/datastore-definitions": "^1.3.6", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/request-handler": "^1.3.6", - "@fluidframework/runtime-definitions": "^1.3.6", - "@fluidframework/runtime-utils": "^1.3.6" - } - }, - "node_modules/@fluidframework/garbage-collector": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/garbage-collector/-/garbage-collector-1.3.6.tgz", - "integrity": "sha512-uJpvkWNzTsLJAmGwu6LUjR8cVoAzlfmhxoudaGrA3DeWhGheDcGVP/hiKht+pMw3u1CCA4AKOfE+0bIOQXyFBA==", + "node_modules/@fluidframework/container-runtime": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/container-runtime/-/container-runtime-2.110.0.tgz", + "integrity": "sha512-cC5XJO2TdlI6H1HbKXP+lbrbQiy5p/6jedgVZBQX6nNI9MyqkdeDlKYuiP0XtMps3W4X9N+cZwyjDkqlOofoJQ==", + "license": "MIT", "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/runtime-definitions": "^1.3.6" + "@fluid-internal/client-utils": "~2.110.0", + "@fluidframework/container-definitions": "~2.110.0", + "@fluidframework/container-runtime-definitions": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/datastore": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "@fluidframework/driver-utils": "~2.110.0", + "@fluidframework/id-compressor": "~2.110.0", + "@fluidframework/runtime-definitions": "~2.110.0", + "@fluidframework/runtime-utils": "~2.110.0", + "@fluidframework/telemetry-utils": "~2.110.0", + "@tylerbu/sorted-btree-es6": "^2.1.1", + "double-ended-queue": "^2.1.0-0", + "lz4js": "^0.2.0", + "semver-ts": "^1.0.3", + "uuid": "^11.1.0" } }, - "node_modules/@fluidframework/gitresources": { - "version": "0.1036.5001", - "resolved": "https://registry.npmjs.org/@fluidframework/gitresources/-/gitresources-0.1036.5001.tgz", - "integrity": "sha512-Beg1A/eR7wCPYYb5u5iqqc092NkWnSvl4XCn2ImA4FDKtnYggD2/KYd9Hp0feM6Z99aU4FYSBidL2NewWlvF7A==" - }, - "node_modules/@fluidframework/ink": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/ink/-/ink-1.3.6.tgz", - "integrity": "sha512-iXXq0vXYAb4sXvdTrd7/s1v+/VzWkFYvd9H39zzyPgK3IOAcp8IBOcu0WK0tQDbTRr4SK4Kg3Zb4593IxFMFhQ==", - "dev": true, + "node_modules/@fluidframework/container-runtime-definitions": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/container-runtime-definitions/-/container-runtime-definitions-2.110.0.tgz", + "integrity": "sha512-OngXutaIefasWbwjJdaSW5luGSjCftye/PtLkBZljwhN9/z/l/d7adAUiQuPp2UN72mosKLQUbFah0GsoEx+bQ==", + "license": "MIT", "dependencies": { - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/datastore-definitions": "^1.3.6", - "@fluidframework/driver-utils": "^1.3.6", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/runtime-definitions": "^1.3.6", - "@fluidframework/shared-object-base": "^1.3.6", - "uuid": "^8.3.1" + "@fluid-internal/client-utils": "~2.110.0", + "@fluidframework/container-definitions": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "@fluidframework/runtime-definitions": "~2.110.0" } }, - "node_modules/@fluidframework/ink/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, + "node_modules/@fluidframework/container-runtime/node_modules/uuid": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" + "uuid": "dist/esm/bin/uuid" } }, - "node_modules/@fluidframework/local-driver": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/local-driver/-/local-driver-1.3.6.tgz", - "integrity": "sha512-R8KO3gqtWmLYwGrPwWXtWKlTMg2I5MehuGBe7L05U9k1yi/P9CNowrdcYLXCNi5IuQ0dxwxR5wmnahns4gFSHA==", - "dev": true, - "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/driver-base": "^1.3.6", - "@fluidframework/driver-definitions": "^1.3.6", - "@fluidframework/driver-utils": "^1.3.6", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/routerlicious-driver": "^1.3.6", - "@fluidframework/server-local-server": "^0.1036.5001", - "@fluidframework/server-services-client": "^0.1036.5001", - "@fluidframework/server-services-core": "^0.1036.5001", - "@fluidframework/server-test-utils": "^0.1036.5001", - "events": "^3.1.0", - "jsrsasign": "^10.5.25", - "url": "^0.11.0", - "uuid": "^8.3.1" - } + "node_modules/@fluidframework/core-interfaces": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/core-interfaces/-/core-interfaces-2.110.0.tgz", + "integrity": "sha512-e8tsTMqk50Ou8o4az8VqyTUnqV7uzIk04xKP8oPyjSJuMffjzAXBre9e/OaurORbuTjN0O1t26AIlkxtogCZ/w==", + "license": "MIT" }, - "node_modules/@fluidframework/local-driver/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" + "node_modules/@fluidframework/core-utils": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/core-utils/-/core-utils-2.110.0.tgz", + "integrity": "sha512-qNL0q73sffopsql3rxhCY4G7acJTp5fcx3QBfcfb15tyZisn7dtS8ZkItxAnzLZ27gKsQg2atnsd4svpnuNAPg==", + "license": "MIT" + }, + "node_modules/@fluidframework/counter": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/counter/-/counter-2.110.0.tgz", + "integrity": "sha512-ILCZ+zBmrdIJoAlZGhu+Zi7OHuxgsfIotepyUK5VXcW2tL8I7wJXr0r6So66gYBvqc9mkoG2XsbxoqLHnz+Pzw==", + "license": "MIT", + "dependencies": { + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/datastore-definitions": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "@fluidframework/driver-utils": "~2.110.0", + "@fluidframework/runtime-definitions": "~2.110.0", + "@fluidframework/shared-object-base": "~2.110.0" } }, - "node_modules/@fluidframework/map": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/map/-/map-1.3.6.tgz", - "integrity": "sha512-CEuDHKLbJGt8SwwyUKoY1ZBkeFcn7Y+XPbm6lqsctYM08Fz2n1IsI6cl7KqppR3xJ2SpGyzDnVzNXeiPyOapfQ==", - "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/container-utils": "^1.3.6", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/datastore-definitions": "^1.3.6", - "@fluidframework/driver-utils": "^1.3.6", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/runtime-definitions": "^1.3.6", - "@fluidframework/runtime-utils": "^1.3.6", - "@fluidframework/shared-object-base": "^1.3.6", - "path-browserify": "^1.0.1" + "node_modules/@fluidframework/datastore": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/datastore/-/datastore-2.110.0.tgz", + "integrity": "sha512-wjFDFrdgoY4uHZrMQji/2IhqA8Eph+x0a1LHq+5E2v1Ayt0NfyXMeR3JS/HCCMWiUZZWl++cFX6791bQ91G3tg==", + "license": "MIT", + "dependencies": { + "@fluid-internal/client-utils": "~2.110.0", + "@fluidframework/container-definitions": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/datastore-definitions": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "@fluidframework/driver-utils": "~2.110.0", + "@fluidframework/id-compressor": "~2.110.0", + "@fluidframework/runtime-definitions": "~2.110.0", + "@fluidframework/runtime-utils": "~2.110.0", + "@fluidframework/telemetry-utils": "~2.110.0", + "uuid": "^11.1.0" } }, - "node_modules/@fluidframework/matrix": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/matrix/-/matrix-1.3.6.tgz", - "integrity": "sha512-hy6Kp7MmoYRWgNI+hDuQNy3mZoQUczWIg1ykxogUvgn7ZJEjRgMs1Rz6K5FJA1eDWPTeJbsx22F1xWLRAJ256g==", - "dev": true, - "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/datastore-definitions": "^1.3.6", - "@fluidframework/merge-tree": "^1.3.6", - "@fluidframework/protocol-base": "^0.1036.5001", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/runtime-definitions": "^1.3.6", - "@fluidframework/runtime-utils": "^1.3.6", - "@fluidframework/shared-object-base": "^1.3.6", - "@fluidframework/telemetry-utils": "^1.3.6", - "@tiny-calc/nano": "0.0.0-alpha.5", - "events": "^3.1.0", - "tslib": "^1.10.0" + "node_modules/@fluidframework/datastore-definitions": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/datastore-definitions/-/datastore-definitions-2.110.0.tgz", + "integrity": "sha512-uZYh6FiwcOug7dD+PTKnj1TE8InlDaqWVspGQbr19fOW2WiA4XTjGLpjIwVa0fDXA/9PWCmFZ3TpQGZRmxP0sw==", + "license": "MIT", + "dependencies": { + "@fluidframework/container-definitions": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "@fluidframework/id-compressor": "~2.110.0", + "@fluidframework/runtime-definitions": "~2.110.0" } }, - "node_modules/@fluidframework/matrix/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "node_modules/@fluidframework/datastore/node_modules/uuid": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } }, - "node_modules/@fluidframework/merge-tree": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/merge-tree/-/merge-tree-1.3.6.tgz", - "integrity": "sha512-a7ZYHpbKO5as+SxKbiqAlxYXK/vmaWY0A8n1O5dTjgElHaJkuxaKKczczr9tBrAxQ7JYNZ0Sq3e6n5hm2gfU4g==", - "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/container-definitions": "^1.3.6", - "@fluidframework/container-utils": "^1.3.6", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/datastore-definitions": "^1.3.6", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/runtime-definitions": "^1.3.6", - "@fluidframework/runtime-utils": "^1.3.6", - "@fluidframework/shared-object-base": "^1.3.6", - "@fluidframework/telemetry-utils": "^1.3.6" + "node_modules/@fluidframework/driver-base": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/driver-base/-/driver-base-2.110.0.tgz", + "integrity": "sha512-Km4UgcL6OxaQw36Ayg2YLwliwzIHh7KlHh9o82BUmLeho9ftK6/8T4G/AscgIoKVkIUNDolo9yM21DOV2CVuXw==", + "license": "MIT", + "dependencies": { + "@fluid-internal/client-utils": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "@fluidframework/driver-utils": "~2.110.0", + "@fluidframework/telemetry-utils": "~2.110.0" } }, - "node_modules/@fluidframework/mocha-test-setup": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/mocha-test-setup/-/mocha-test-setup-1.3.6.tgz", - "integrity": "sha512-MfIU2oCCw53nP7ey8rftrvvcoP13IY2Yh23J7RuutU/POTgZ956292vnHgvQgHgmJjWJJBf7iDqVAb6Q8EakUQ==", - "dev": true, + "node_modules/@fluidframework/driver-definitions": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/driver-definitions/-/driver-definitions-2.110.0.tgz", + "integrity": "sha512-3faCGqIYMGqjfhaI90cJHaCMQiaquFnBh0A0Pu6GehNzGLRK19IvbeE1CQC3FJ96KkxDeD5j8dv7G6peGSkULA==", + "license": "MIT", "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/test-driver-definitions": "^1.3.6", - "mocha": "^10.0.0" + "@fluidframework/core-interfaces": "~2.110.0" } }, - "node_modules/@fluidframework/odsp-doclib-utils": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/odsp-doclib-utils/-/odsp-doclib-utils-1.3.6.tgz", - "integrity": "sha512-Wp5/7KZOPaiDVT5gdorW3fk8M8ZKXX4wYCZO+EU+rnoh6t9k+cXtWGNmAE68/vPOjDH+8UPz2P/yPereZja2mg==", - "dev": true, + "node_modules/@fluidframework/driver-utils": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/driver-utils/-/driver-utils-2.110.0.tgz", + "integrity": "sha512-ZdBFFbHuApmxUTY+XqOQZU6sI4dDUsG1l8a7XHYd7B4vWVk2+QiQKkp+3JlKsVZjwotQipbg0YQrbKaMbwZhpg==", + "license": "MIT", "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/driver-definitions": "^1.3.6", - "@fluidframework/driver-utils": "^1.3.6", - "@fluidframework/odsp-driver-definitions": "^1.3.6", - "@fluidframework/telemetry-utils": "^1.3.6", - "node-fetch": "^2.6.1" + "@fluid-internal/client-utils": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "@fluidframework/telemetry-utils": "~2.110.0", + "lz4js": "^0.2.0", + "uuid": "^11.1.0" } }, - "node_modules/@fluidframework/odsp-driver": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/odsp-driver/-/odsp-driver-1.3.6.tgz", - "integrity": "sha512-4t/XcvGcFL0ElPuQrA3Aq3iB7ZZ50soCgdKoH+mKtkUgoB0DqAYKgQDB61tLQpYFr07gfpeBUHv+6hMZ1v7q5A==", - "dev": true, - "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/driver-base": "^1.3.6", - "@fluidframework/driver-definitions": "^1.3.6", - "@fluidframework/driver-utils": "^1.3.6", - "@fluidframework/gitresources": "^0.1036.5001", - "@fluidframework/odsp-doclib-utils": "^1.3.6", - "@fluidframework/odsp-driver-definitions": "^1.3.6", - "@fluidframework/protocol-base": "^0.1036.5001", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/telemetry-utils": "^1.3.6", - "abort-controller": "^3.0.0", - "node-fetch": "^2.6.1", - "socket.io-client": "^4.4.1", - "uuid": "^8.3.1" + "node_modules/@fluidframework/driver-utils/node_modules/uuid": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" } }, - "node_modules/@fluidframework/odsp-driver-definitions": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/odsp-driver-definitions/-/odsp-driver-definitions-1.3.6.tgz", - "integrity": "sha512-iTolXZ12yrB/05ZNHRYy+AKxX3vMmV1YDzeTOzhS1L7nn6SyDAlPx4BZMeLwEPwqA0OzQjYAAWgyW3FV28jmNw==", + "node_modules/@fluidframework/eslint-config-fluid": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@fluidframework/eslint-config-fluid/-/eslint-config-fluid-8.1.0.tgz", + "integrity": "sha512-SNuj/gKmx4zkgTQO24gF7e+UMe2n/V4MBQWjrO8YJ+vPOivw3RwJTQkJgiqqL2e5F659TTlwKt+tQ1OCDKvuPg==", "dev": true, + "license": "MIT", "dependencies": { - "@fluidframework/driver-definitions": "^1.3.6" - } - }, - "node_modules/@fluidframework/odsp-driver/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "@fluid-internal/eslint-plugin-fluid": "^0.4.0", + "@rushstack/eslint-patch": "~1.12.0", + "@rushstack/eslint-plugin": "~0.19.0", + "@rushstack/eslint-plugin-security": "~0.11.0", + "@typescript-eslint/eslint-plugin": "~7.18.0", + "@typescript-eslint/parser": "~7.18.0", + "eslint-config-biome": "~2.1.3", + "eslint-config-prettier": "~10.1.8", + "eslint-import-resolver-typescript": "~4.4.4", + "eslint-plugin-eslint-comments": "~3.2.0", + "eslint-plugin-import-x": "~4.16.1", + "eslint-plugin-jsdoc": "~55.0.2", + "eslint-plugin-promise": "~7.2.1", + "eslint-plugin-react": "~7.37.5", + "eslint-plugin-react-hooks": "~5.2.0", + "eslint-plugin-tsdoc": "~0.4.0", + "eslint-plugin-unicorn": "~48.0.1", + "eslint-plugin-unused-imports": "~4.2.0" + } + }, + "node_modules/@fluidframework/eslint-config-fluid/node_modules/@typescript-eslint/types": { + "version": "8.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.62.0.tgz", + "integrity": "sha512-KvAclkktORPvM54TgLgA4z9HIV1M8zOgw9ZVNXl9f/8dLYfXYX1wkMXP7qmabpijQRV5bHJLOmoyGQbLMaUYeg==", "dev": true, - "bin": { - "uuid": "dist/bin/uuid" + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@fluidframework/odsp-urlresolver": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/odsp-urlresolver/-/odsp-urlresolver-1.3.6.tgz", - "integrity": "sha512-IvS6BQQyVBfZmV1EMqrzF9p32DZIosXIHbZjdECW5MGn1V8Dqv6zaMx5tS0hqSxGauAKLPoZ37kwzyX8wEQxaA==", + "node_modules/@fluidframework/eslint-config-fluid/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, - "dependencies": { - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/driver-definitions": "^1.3.6", - "@fluidframework/odsp-driver": "^1.3.6", - "@fluidframework/odsp-driver-definitions": "^1.3.6" + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" } }, - "node_modules/@fluidframework/ordered-collection": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/ordered-collection/-/ordered-collection-1.3.6.tgz", - "integrity": "sha512-OCcQ86lb+LbZXyGN4XxsbfwoAcVyCj0S4zG82oI7IRl8jgQtRkXc0nmvIyufQidLMmMzTwTB/LppYu1MJWMqGg==", + "node_modules/@fluidframework/eslint-config-fluid/node_modules/brace-expansion": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", "dev": true, + "license": "MIT", "dependencies": { - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/datastore-definitions": "^1.3.6", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/runtime-definitions": "^1.3.6", - "@fluidframework/runtime-utils": "^1.3.6", - "@fluidframework/shared-object-base": "^1.3.6", - "uuid": "^8.3.1" + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" } }, - "node_modules/@fluidframework/ordered-collection/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "node_modules/@fluidframework/eslint-config-fluid/node_modules/eslint-config-prettier": { + "version": "10.1.8", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, + "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" + "eslint-config-prettier": "bin/cli.js" + }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, + "peerDependencies": { + "eslint": ">=7.0.0" } }, - "node_modules/@fluidframework/protocol-base": { - "version": "0.1036.5001", - "resolved": "https://registry.npmjs.org/@fluidframework/protocol-base/-/protocol-base-0.1036.5001.tgz", - "integrity": "sha512-Btjy2bWVbVsmzNTBxTQZ9l/WXljsjDpGbBgJsn9GLacrTG9aDDtIVMXuwLAcEV1IVkxGcIipXryvfhbPHDYcMg==", + "node_modules/@fluidframework/eslint-config-fluid/node_modules/eslint-import-resolver-typescript": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-4.4.5.tgz", + "integrity": "sha512-nbE5XLph6TLtGYcu/U6e6ZVXyKBhbDWK5cLGk76eJ7NdZpwf1P9EFkpt1Z01mNZNrrilsAYWKH6zUkL4reoXbw==", + "dev": true, + "license": "ISC", "dependencies": { - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/gitresources": "^0.1036.5001", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "lodash": "^4.17.21" + "debug": "^4.4.1", + "eslint-import-context": "^0.1.8", + "get-tsconfig": "^4.10.1", + "is-bun-module": "^2.0.0", + "stable-hash-x": "^0.2.0", + "tinyglobby": "^0.2.14", + "unrs-resolver": "^1.7.11" + }, + "engines": { + "node": "^16.17.0 || >=18.6.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-import-resolver-typescript" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } } }, - "node_modules/@fluidframework/protocol-definitions": { - "version": "0.1028.2000", - "resolved": "https://registry.npmjs.org/@fluidframework/protocol-definitions/-/protocol-definitions-0.1028.2000.tgz", - "integrity": "sha512-ZUPCmPFcK7UAK4RkfVWfzQPAWFvYNm6ywP51V42YC38gCGye+Epvyr3beA+FSaHPIZGxm5+Uw52+ykTvmDb2UA==", + "node_modules/@fluidframework/eslint-config-fluid/node_modules/eslint-plugin-import-x": { + "version": "4.16.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.16.2.tgz", + "integrity": "sha512-rM9K8UBHcWKpzQzStn1YRN2T5NvdeIfSVoKu/lKF41znQXHAUcBbYXe5wd6GNjZjTrP7viQ49n1D83x/2gYgIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@package-json/types": "^0.0.12", + "@typescript-eslint/types": "^8.56.0", + "comment-parser": "^1.4.1", + "debug": "^4.4.1", + "eslint-import-context": "^0.1.9", + "is-glob": "^4.0.3", + "minimatch": "^9.0.3 || ^10.1.2", + "semver": "^7.7.2", + "stable-hash-x": "^0.2.0", + "unrs-resolver": "^1.9.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-import-x" + }, + "peerDependencies": { + "@typescript-eslint/utils": "^8.56.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "eslint-import-resolver-node": "*" + }, + "peerDependenciesMeta": { + "@typescript-eslint/utils": { + "optional": true + }, + "eslint-import-resolver-node": { + "optional": true + } + } + }, + "node_modules/@fluidframework/eslint-config-fluid/node_modules/eslint-plugin-react-hooks": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", + "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, + "node_modules/@fluidframework/eslint-config-fluid/node_modules/eslint-plugin-unused-imports": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.2.0.tgz", + "integrity": "sha512-hLbJ2/wnjKq4kGA9AUaExVFIbNzyxYdVo49QZmKCnhk5pc9wcYRbfgLHvWJ8tnsdcseGhoUAddm9gn/lt+d74w==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0", + "eslint": "^9.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + } + } + }, + "node_modules/@fluidframework/eslint-config-fluid/node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@fluidframework/fluid-static": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/fluid-static/-/fluid-static-2.110.0.tgz", + "integrity": "sha512-ul0N0Decc8rtUTDBYRf/em5aOtTwexL+hhbACJKaOUzdqublVvbnWKrj6D/2IDS15cIHH12ODaBLXkheWONgSw==", + "license": "MIT", + "dependencies": { + "@fluid-internal/client-utils": "~2.110.0", + "@fluid-internal/presence-definitions": "~2.110.0", + "@fluid-internal/presence-runtime": "~2.110.0", + "@fluidframework/aqueduct": "~2.110.0", + "@fluidframework/container-definitions": "~2.110.0", + "@fluidframework/container-loader": "~2.110.0", + "@fluidframework/container-runtime": "~2.110.0", + "@fluidframework/container-runtime-definitions": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/datastore-definitions": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "@fluidframework/request-handler": "~2.110.0", + "@fluidframework/runtime-definitions": "~2.110.0", + "@fluidframework/runtime-utils": "~2.110.0", + "@fluidframework/shared-object-base": "~2.110.0", + "@fluidframework/telemetry-utils": "~2.110.0", + "@fluidframework/tree": "~2.110.0", + "semver-ts": "^1.0.3" + } + }, + "node_modules/@fluidframework/gitresources": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@fluidframework/gitresources/-/gitresources-7.0.1.tgz", + "integrity": "sha512-sFEdPL46Hz/xuP51nwT19JubSeb3fBBrNQXwnRLCcmaX+fXdxg7rkyVLTgue0swgdJ73Oh98eTYpxplkq+FSJA==", + "license": "MIT" + }, + "node_modules/@fluidframework/id-compressor": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/id-compressor/-/id-compressor-2.110.0.tgz", + "integrity": "sha512-XCiTB2NLx2vb85jh8cj/7L9ZiNpf3R5gjo9j0Bol/H33ca0/GsBgYx2RoYj8mc4CliyMo7DdX4jMBjLvfgBHHQ==", + "license": "MIT", + "dependencies": { + "@fluid-internal/client-utils": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/telemetry-utils": "~2.110.0", + "@tylerbu/sorted-btree-es6": "^2.1.1", + "uuid": "^11.1.0" + } + }, + "node_modules/@fluidframework/id-compressor/node_modules/uuid": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, + "node_modules/@fluidframework/local-driver": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/local-driver/-/local-driver-2.110.0.tgz", + "integrity": "sha512-ATRyhSC5ktDRx+M3LcLK3Ei12HkzBDOS8Nv175sc8H84CpdQ+bxIs804pGxUH4W9QeCjvWfUCm4tRl0GT8O++g==", + "license": "MIT", + "dependencies": { + "@fluid-internal/client-utils": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/driver-base": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "@fluidframework/driver-utils": "~2.110.0", + "@fluidframework/protocol-base": "^7.0.1", + "@fluidframework/routerlicious-driver": "~2.110.0", + "@fluidframework/server-local-server": "^7.0.1", + "@fluidframework/server-services-client": "^7.0.1", + "@fluidframework/server-services-core": "^7.0.1", + "@fluidframework/server-test-utils": "^7.0.1", + "@fluidframework/telemetry-utils": "~2.110.0", + "jsrsasign": "^11.1.1", + "uuid": "^11.1.0" + } + }, + "node_modules/@fluidframework/local-driver/node_modules/uuid": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, + "node_modules/@fluidframework/map": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/map/-/map-2.110.0.tgz", + "integrity": "sha512-sGeqftNvFxIgJ7OaUbq6fFLYLVm9f9sRpimGNkJQK8nDxGWnik/soldfuTulLqwDznckv5ml/vhiIroNg0iNEw==", + "license": "MIT", + "dependencies": { + "@fluid-internal/client-utils": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/datastore-definitions": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "@fluidframework/driver-utils": "~2.110.0", + "@fluidframework/runtime-definitions": "~2.110.0", + "@fluidframework/runtime-utils": "~2.110.0", + "@fluidframework/shared-object-base": "~2.110.0", + "@fluidframework/telemetry-utils": "~2.110.0", + "path-browserify": "^1.0.1" + } + }, + "node_modules/@fluidframework/matrix": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/matrix/-/matrix-2.110.0.tgz", + "integrity": "sha512-KBkaNehpDKlvLLk0FcdUzcHa9JZeaY1epspN6AfJiKoNhFQC+E2RwSXgPAtxCzCtp2mb+nbUEVTLwK4+x+VtcQ==", + "license": "MIT", + "dependencies": { + "@fluid-internal/client-utils": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/datastore-definitions": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "@fluidframework/driver-utils": "~2.110.0", + "@fluidframework/merge-tree": "~2.110.0", + "@fluidframework/runtime-definitions": "~2.110.0", + "@fluidframework/runtime-utils": "~2.110.0", + "@fluidframework/shared-object-base": "~2.110.0", + "@fluidframework/telemetry-utils": "~2.110.0", + "@tiny-calc/nano": "0.0.0-alpha.5", + "double-ended-queue": "^2.1.0-0" + } + }, + "node_modules/@fluidframework/merge-tree": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/merge-tree/-/merge-tree-2.110.0.tgz", + "integrity": "sha512-pUuXoxOvz3Rp2I972ne1LRq83mZv1coqjEKj+J3PdfcpclOnmE1X0aXYOeDWUmxU24wx/m7ARYJrTmGAkKG6ag==", + "license": "MIT", + "dependencies": { + "@fluid-internal/client-utils": "~2.110.0", + "@fluidframework/container-definitions": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/datastore-definitions": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "@fluidframework/runtime-definitions": "~2.110.0", + "@fluidframework/runtime-utils": "~2.110.0", + "@fluidframework/shared-object-base": "~2.110.0", + "@fluidframework/telemetry-utils": "~2.110.0" + } + }, + "node_modules/@fluidframework/mocha-test-setup": { + "version": "2.0.0-rc.1.0.9", + "resolved": "https://registry.npmjs.org/@fluidframework/mocha-test-setup/-/mocha-test-setup-2.0.0-rc.1.0.9.tgz", + "integrity": "sha512-yng+1zA+9q6LEhAC9HvAIxYajeo+HAKCYZoPc5Ggpn3R2mBStogyBsDE1T2J/KiJxHsqrdaZXFWxX2gEi8FdzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@fluidframework/core-interfaces": ">=2.0.0-rc.1.0.9 <2.0.0-rc.1.1.0", + "@fluidframework/test-driver-definitions": ">=2.0.0-rc.1.0.9 <2.0.0-rc.1.1.0", + "mocha": "^10.2.0", + "source-map-support": "^0.5.21" + } + }, + "node_modules/@fluidframework/mocha-test-setup/node_modules/@fluidframework/core-interfaces": { + "version": "2.0.0-rc.1.0.9", + "resolved": "https://registry.npmjs.org/@fluidframework/core-interfaces/-/core-interfaces-2.0.0-rc.1.0.9.tgz", + "integrity": "sha512-o7J+UNzfSU7ImQmT96TK27UJ6o2LB1sKBWxyaAsl5FMicBESIX6669yXE/jggBXoDZndUZfISBXRukDjhiQy0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@fluidframework/odsp-doclib-utils": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/odsp-doclib-utils/-/odsp-doclib-utils-2.110.0.tgz", + "integrity": "sha512-K5/KHSVulW41K/RpJXGNP3xAXpFX4sjFsk9pq3vcHFpjKYR4M4L+SpLElbDaSjmW4jU+ZOwVS2rjrWguKPDzgA==", + "license": "MIT", + "dependencies": { + "@fluid-internal/client-utils": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "@fluidframework/driver-utils": "~2.110.0", + "@fluidframework/odsp-driver-definitions": "~2.110.0", + "@fluidframework/telemetry-utils": "~2.110.0" + } + }, + "node_modules/@fluidframework/odsp-driver": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/odsp-driver/-/odsp-driver-2.110.0.tgz", + "integrity": "sha512-p4QEQVvs+SmuTvKt6YMnb0V6GOLluyOJRt5wASzavLaZQXpTTrXhBwGIhxcFydue1uxBfmMaCLAFYV8MjZRq9w==", + "license": "MIT", + "dependencies": { + "@fluid-internal/client-utils": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/driver-base": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "@fluidframework/driver-utils": "~2.110.0", + "@fluidframework/odsp-doclib-utils": "~2.110.0", + "@fluidframework/odsp-driver-definitions": "~2.110.0", + "@fluidframework/telemetry-utils": "~2.110.0", + "socket.io-client": "^4.8.3", + "uuid": "^11.1.0" + } + }, + "node_modules/@fluidframework/odsp-driver-definitions": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/odsp-driver-definitions/-/odsp-driver-definitions-2.110.0.tgz", + "integrity": "sha512-4cOdqdK92yca4cH7k/DTHNyX/QkbcH9ed7m4wVua2ApYg4hGI3qBbJFp8VfGQ0JfC773HmU5j6WX1Wh/GowXPA==", + "license": "MIT", + "dependencies": { + "@fluidframework/driver-definitions": "~2.110.0" + } + }, + "node_modules/@fluidframework/odsp-driver/node_modules/uuid": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, + "node_modules/@fluidframework/ordered-collection": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/ordered-collection/-/ordered-collection-2.110.0.tgz", + "integrity": "sha512-cezj42htwF2LleVirRsmcHEjUxP7wvx3VrEp4KC2ns7m4fP3lmfS7npHo1Iejf28bq1a34WnErp2vq25SqK+6Q==", + "license": "MIT", + "dependencies": { + "@fluid-internal/client-utils": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/datastore-definitions": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "@fluidframework/runtime-definitions": "~2.110.0", + "@fluidframework/runtime-utils": "~2.110.0", + "@fluidframework/shared-object-base": "~2.110.0", + "@fluidframework/telemetry-utils": "~2.110.0", + "uuid": "^11.1.0" + } + }, + "node_modules/@fluidframework/ordered-collection/node_modules/uuid": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, + "node_modules/@fluidframework/protocol-base": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@fluidframework/protocol-base/-/protocol-base-7.0.1.tgz", + "integrity": "sha512-WfMf+vN0OmUHl0xJIsY6jnnsF5p27apMRd38pC9TlMx1URt+3C2fV4WLEybn2wYEGepYcK03ZMqe6I+DXt7/6g==", + "license": "MIT", "dependencies": { - "@fluidframework/common-definitions": "^0.20.1" + "@fluidframework/common-utils": "^3.1.0", + "@fluidframework/gitresources": "7.0.1", + "@fluidframework/protocol-definitions": "^3.2.0", + "events_pkg": "npm:events@^3.1.0" } }, + "node_modules/@fluidframework/protocol-definitions": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@fluidframework/protocol-definitions/-/protocol-definitions-3.2.0.tgz", + "integrity": "sha512-xgcyMN4uF6dAp2/XYFSHvGFITIV7JbVt3itA+T0c71/lZjq/HU/a/ClPIxfl9AEN0RbtuR/1n5LP4FXSV9j0hA==", + "license": "MIT" + }, "node_modules/@fluidframework/register-collection": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/register-collection/-/register-collection-1.3.6.tgz", - "integrity": "sha512-CFj3l5rZZh7Imxaf7LvhMsACPTd3cdyNw6exBuVI5xOfsOuazSfuShIwCijF94QRujufmAtnvupDGv8CYlfZXg==", + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/register-collection/-/register-collection-2.110.0.tgz", + "integrity": "sha512-EvXMqSt53OQeTc+XjOwPDWbo/vlt2KP131i+VPx4IoKGCxvSgnmwSiRCYB+ptEiHlp8hvoua4RRU8VcVO430rQ==", + "license": "MIT", "dependencies": { - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/datastore-definitions": "^1.3.6", - "@fluidframework/protocol-base": "^0.1036.5001", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/runtime-definitions": "^1.3.6", - "@fluidframework/shared-object-base": "^1.3.6" + "@fluid-internal/client-utils": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/datastore-definitions": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "@fluidframework/driver-utils": "~2.110.0", + "@fluidframework/runtime-definitions": "~2.110.0", + "@fluidframework/shared-object-base": "~2.110.0" } }, "node_modules/@fluidframework/request-handler": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/request-handler/-/request-handler-1.3.6.tgz", - "integrity": "sha512-4z0XRVuj3mu6ZYceUbTf/DZfRt1u0cClnpVZPthEs26QSk6LJvEpt5UBE3oIGkESoxZ3LHtAnkS2zCEl8jcrFw==", + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/request-handler/-/request-handler-2.110.0.tgz", + "integrity": "sha512-gkYL0ILULv5llCEFhD+QysAeqbEYTTm7UqI+3l28xXQzEB1h3au+phCQF9mC5+I/UxlV7XNIlpGKPVk5d5wvtw==", + "license": "MIT", "dependencies": { - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/container-runtime-definitions": "^1.3.6", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/runtime-definitions": "^1.3.6", - "@fluidframework/runtime-utils": "^1.3.6" + "@fluidframework/container-runtime-definitions": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/runtime-definitions": "~2.110.0", + "@fluidframework/runtime-utils": "~2.110.0" } }, "node_modules/@fluidframework/routerlicious-driver": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/routerlicious-driver/-/routerlicious-driver-1.3.6.tgz", - "integrity": "sha512-b9NXLWI7YH4l2dEkgjDuIF9BNb1ggxkzS8ZtZpr+eBtegRN+E+WSbkR7JCPwrDmA+vPa9z0mXNS88ZeCwnQp3A==", - "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/driver-base": "^1.3.6", - "@fluidframework/driver-definitions": "^1.3.6", - "@fluidframework/driver-utils": "^1.3.6", - "@fluidframework/gitresources": "^0.1036.5001", - "@fluidframework/protocol-base": "^0.1036.5001", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/server-services-client": "^0.1036.5001", - "@fluidframework/telemetry-utils": "^1.3.6", - "cross-fetch": "^3.1.5", + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/routerlicious-driver/-/routerlicious-driver-2.110.0.tgz", + "integrity": "sha512-rGs02Na5gB47FIodqwareBfJE89UuU3PoP1GzrdqZIMTCF30ATqI3kgVC7x4/hKjTuxM6gjSTSNvTR9qt4yjAw==", + "license": "MIT", + "dependencies": { + "@fluid-internal/client-utils": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/driver-base": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "@fluidframework/driver-utils": "~2.110.0", + "@fluidframework/server-services-client": "^7.0.1", + "@fluidframework/telemetry-utils": "~2.110.0", "json-stringify-safe": "5.0.1", - "querystring": "^0.2.0", - "socket.io-client": "^4.4.1", - "url-parse": "^1.5.8", - "uuid": "^8.3.1" - } - }, - "node_modules/@fluidframework/routerlicious-driver/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" + "socket.io-client": "^4.8.3" } }, "node_modules/@fluidframework/runtime-definitions": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/runtime-definitions/-/runtime-definitions-1.3.6.tgz", - "integrity": "sha512-sFCUkN4sCz1ww7XKhIFiiXuaUtrps8Dd4h0VaYLsvzkH9bD/lcbbcvgmaMmqPa3tOy0ROsLAM5QSr5jBYipidw==", + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/runtime-definitions/-/runtime-definitions-2.110.0.tgz", + "integrity": "sha512-HJQaTk/9AhihPQal81pjVsjbHYvuobQ7Y9JrNHxsC1AfoCXVn7M5xHAcrzqjJyGaMlx/Nc4gNgvcLQWJPjbXXQ==", + "license": "MIT", "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/container-definitions": "^1.3.6", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/driver-definitions": "^1.3.6", - "@fluidframework/protocol-definitions": "^0.1028.2000" + "@fluid-internal/client-utils": "~2.110.0", + "@fluidframework/container-definitions": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "@fluidframework/id-compressor": "~2.110.0", + "@fluidframework/telemetry-utils": "~2.110.0" } }, "node_modules/@fluidframework/runtime-utils": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/runtime-utils/-/runtime-utils-1.3.6.tgz", - "integrity": "sha512-Yl0oWTcUwgDBWIaW6UsyfHE9D5yhmY11lx5ij3RcEn2Up07mD7+DzFXvxXTjdCioc4B0ssad70vvGJKJOwk6Nw==", - "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/container-definitions": "^1.3.6", - "@fluidframework/container-runtime-definitions": "^1.3.6", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/datastore-definitions": "^1.3.6", - "@fluidframework/garbage-collector": "^1.3.6", - "@fluidframework/protocol-base": "^0.1036.5001", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/runtime-definitions": "^1.3.6", - "@fluidframework/telemetry-utils": "^1.3.6" + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/runtime-utils/-/runtime-utils-2.110.0.tgz", + "integrity": "sha512-MQozb8pvKtZipMGlbC5THFoiAtpfpLopD/4OlzQ1khBhBO5gnz1pESxSGjtQycnHbUdDjIVgX+j1/bAZC++s+w==", + "license": "MIT", + "dependencies": { + "@fluid-internal/client-utils": "~2.110.0", + "@fluidframework/container-definitions": "~2.110.0", + "@fluidframework/container-runtime-definitions": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/datastore-definitions": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "@fluidframework/driver-utils": "~2.110.0", + "@fluidframework/runtime-definitions": "~2.110.0", + "@fluidframework/telemetry-utils": "~2.110.0", + "semver-ts": "^1.0.3" } }, "node_modules/@fluidframework/sequence": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/sequence/-/sequence-1.3.6.tgz", - "integrity": "sha512-XGtwifGkakcUxAnaEyM23CaG/avK1a87odb2uhbiwP2k3g55aSe2PsOhmtJVVrs1Yv775Xc1jGUotRKiNzLY7w==", - "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/container-utils": "^1.3.6", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/datastore-definitions": "^1.3.6", - "@fluidframework/merge-tree": "^1.3.6", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/runtime-definitions": "^1.3.6", - "@fluidframework/runtime-utils": "^1.3.6", - "@fluidframework/shared-object-base": "^1.3.6", - "@fluidframework/telemetry-utils": "^1.3.6", - "uuid": "^8.3.1" + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/sequence/-/sequence-2.110.0.tgz", + "integrity": "sha512-N/lZn/BmliQ2dZd2pFRi0Wkw7chfNgx5uBAYdhqO5wJUK3MqKihGYJXrMuoahIYEcNO/4bdADVLdvpAOkpTUvg==", + "license": "MIT", + "dependencies": { + "@fluid-internal/client-utils": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/datastore-definitions": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "@fluidframework/merge-tree": "~2.110.0", + "@fluidframework/runtime-definitions": "~2.110.0", + "@fluidframework/runtime-utils": "~2.110.0", + "@fluidframework/shared-object-base": "~2.110.0", + "@fluidframework/telemetry-utils": "~2.110.0", + "double-ended-queue": "^2.1.0-0", + "uuid": "^11.1.0" } }, "node_modules/@fluidframework/sequence/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" + "uuid": "dist/esm/bin/uuid" } }, "node_modules/@fluidframework/server-lambdas": { - "version": "0.1036.5001", - "resolved": "https://registry.npmjs.org/@fluidframework/server-lambdas/-/server-lambdas-0.1036.5001.tgz", - "integrity": "sha512-0Wc1k7WqLZatUdoV09flzMgmumBWR+8AOKJNqZSDr4XcEOfdyLIpEjDgIelkJm9JFC1RLpcNcVR5k14RuWq2CQ==", - "dev": true, - "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/gitresources": "^0.1036.5001", - "@fluidframework/protocol-base": "^0.1036.5001", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/server-lambdas-driver": "^0.1036.5001", - "@fluidframework/server-services-client": "^0.1036.5001", - "@fluidframework/server-services-core": "^0.1036.5001", - "@fluidframework/server-services-telemetry": "^0.1036.5001", - "@types/semver": "^6.0.1", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@fluidframework/server-lambdas/-/server-lambdas-7.0.1.tgz", + "integrity": "sha512-FVFq1Gt3b+JYm8wg68QyxHluNkR6T8rGKwAlf1AJ1zCHy1E6DPsR0Gn86gAWYfKw/w/gzTBofoogIaozHHskbQ==", + "license": "MIT", + "dependencies": { + "@fluidframework/common-utils": "^3.1.0", + "@fluidframework/gitresources": "7.0.1", + "@fluidframework/protocol-base": "7.0.1", + "@fluidframework/protocol-definitions": "^3.2.0", + "@fluidframework/server-lambdas-driver": "7.0.1", + "@fluidframework/server-services-client": "7.0.1", + "@fluidframework/server-services-core": "7.0.1", + "@fluidframework/server-services-telemetry": "7.0.1", + "@types/semver": "^7.7.0", + "assert": "^2.0.0", "async": "^3.2.2", - "axios": "^0.26.0", + "axios": "^1.8.4", + "buffer": "^6.0.3", "double-ended-queue": "^2.1.0-0", + "events": "^3.1.0", "json-stringify-safe": "^5.0.1", "lodash": "^4.17.21", "nconf": "^0.12.0", - "semver": "^6.3.0", + "opossum": "^8.1.4", + "semver": "^7.7.1", + "serialize-error": "^8.1.0", "sha.js": "^2.4.11", - "uuid": "^8.3.1" + "uuid": "^11.1.0" } }, "node_modules/@fluidframework/server-lambdas-driver": { - "version": "0.1036.5001", - "resolved": "https://registry.npmjs.org/@fluidframework/server-lambdas-driver/-/server-lambdas-driver-0.1036.5001.tgz", - "integrity": "sha512-YD4dDev+2niL7EUtroa6wA6BlkaTpI7TGbBjD/xQcKclGfk52TjwbSJ30caccQNafgHsKXAWNZmFHHMUgmQa9A==", - "dev": true, + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@fluidframework/server-lambdas-driver/-/server-lambdas-driver-7.0.1.tgz", + "integrity": "sha512-pzpPPCgnVdGu2qcCAXZbur/2tx5O1qp5n06+BdKq1aZsGs5vNfc9ds+KiueiXBFvvoSa3f+AXUjqWwPQopApZQ==", + "license": "MIT", "dependencies": { - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/server-services-client": "^0.1036.5001", - "@fluidframework/server-services-core": "^0.1036.5001", - "@fluidframework/server-services-telemetry": "^0.1036.5001", + "@fluidframework/common-utils": "^3.1.0", + "@fluidframework/server-services-client": "7.0.1", + "@fluidframework/server-services-core": "7.0.1", + "@fluidframework/server-services-telemetry": "7.0.1", + "assert": "^2.0.0", "async": "^3.2.2", - "lodash": "^4.17.21" - } - }, - "node_modules/@fluidframework/server-lambdas/node_modules/@types/semver": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-6.2.3.tgz", - "integrity": "sha512-KQf+QAMWKMrtBMsB8/24w53tEsxllMj6TuA80TT/5igJalLI/zm0L3oXRbIAl4Ohfc85gyHX/jhMwsVkmhLU4A==", - "dev": true - }, - "node_modules/@fluidframework/server-lambdas/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" + "events": "^3.1.0", + "lodash": "^4.17.21", + "nconf": "^0.12.0", + "serialize-error": "^8.1.0" } }, "node_modules/@fluidframework/server-lambdas/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" + "uuid": "dist/esm/bin/uuid" } }, "node_modules/@fluidframework/server-local-server": { - "version": "0.1036.5001", - "resolved": "https://registry.npmjs.org/@fluidframework/server-local-server/-/server-local-server-0.1036.5001.tgz", - "integrity": "sha512-uAhILyeAoLOO6RQHz7hpznSFPpOM0uAfGqg+DxwcGhf4EYoC2LNpnhytptKiZQj7p//Ln5sv0asVYnRgRRaj1w==", - "dev": true, - "dependencies": { - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/server-lambdas": "^0.1036.5001", - "@fluidframework/server-memory-orderer": "^0.1036.5001", - "@fluidframework/server-services-client": "^0.1036.5001", - "@fluidframework/server-services-core": "^0.1036.5001", - "@fluidframework/server-services-telemetry": "^0.1036.5001", - "@fluidframework/server-test-utils": "^0.1036.5001", - "debug": "^4.1.1", - "jsrsasign": "^10.2.0", - "uuid": "^8.3.1" + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@fluidframework/server-local-server/-/server-local-server-7.0.1.tgz", + "integrity": "sha512-MjszPW3Io2/wITc5qCxQlhocRssobDePYOicLccWKItIZ3XuN2wAp33+pOYte9ImYvlQlV4M2F6ratYppn/Nrg==", + "license": "MIT", + "dependencies": { + "@fluidframework/common-utils": "^3.1.0", + "@fluidframework/protocol-definitions": "^3.2.0", + "@fluidframework/server-lambdas": "7.0.1", + "@fluidframework/server-memory-orderer": "7.0.1", + "@fluidframework/server-services-client": "7.0.1", + "@fluidframework/server-services-core": "7.0.1", + "@fluidframework/server-services-telemetry": "7.0.1", + "@fluidframework/server-test-utils": "7.0.1", + "debug": "^4.3.4", + "events_pkg": "npm:events@^3.1.0", + "jsrsasign": "^11.0.0", + "uuid": "^11.1.0" } }, "node_modules/@fluidframework/server-local-server/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" + "uuid": "dist/esm/bin/uuid" } }, "node_modules/@fluidframework/server-memory-orderer": { - "version": "0.1036.5001", - "resolved": "https://registry.npmjs.org/@fluidframework/server-memory-orderer/-/server-memory-orderer-0.1036.5001.tgz", - "integrity": "sha512-sE7+OT8MdriTswZq8BEKzGWqTWpYPKcWaUaxJjFiH3zOZjHrAn39KzFBib7R49aqK3VddvWzDb6w7Vp1B+LTNw==", - "dev": true, - "dependencies": { - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/protocol-base": "^0.1036.5001", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/server-lambdas": "^0.1036.5001", - "@fluidframework/server-services-client": "^0.1036.5001", - "@fluidframework/server-services-core": "^0.1036.5001", - "@fluidframework/server-services-telemetry": "^0.1036.5001", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@fluidframework/server-memory-orderer/-/server-memory-orderer-7.0.1.tgz", + "integrity": "sha512-GHTtnyY7IwpA6BzNJO8VDX0SU3Bj8EXDOw86axPx2JkkDnuW5KFKpvGUugJ6cAkQcqFu/JWzFTm444VLYNOChQ==", + "license": "MIT", + "dependencies": { + "@fluidframework/common-utils": "^3.1.0", + "@fluidframework/protocol-base": "7.0.1", + "@fluidframework/protocol-definitions": "^3.2.0", + "@fluidframework/server-lambdas": "7.0.1", + "@fluidframework/server-services-client": "7.0.1", + "@fluidframework/server-services-core": "7.0.1", + "@fluidframework/server-services-telemetry": "7.0.1", "@types/debug": "^4.1.5", "@types/double-ended-queue": "^2.1.0", "@types/lodash": "^4.14.118", - "@types/node": "^14.18.0", + "@types/node": "^18.19.39", "@types/ws": "^6.0.1", - "debug": "^4.1.1", + "assert": "^2.0.0", + "debug": "^4.3.4", "double-ended-queue": "^2.1.0-0", + "events": "^3.1.0", "lodash": "^4.17.21", "sillyname": "^0.1.0", - "uuid": "^8.3.1", - "ws": "^7.4.6" + "uuid": "^11.1.0", + "ws": "^7.5.10" } }, "node_modules/@fluidframework/server-memory-orderer/node_modules/@types/node": { - "version": "14.18.47", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.47.tgz", - "integrity": "sha512-OuJi8bIng4wYHHA3YpKauL58dZrPxro3d0tabPHyiNF8rKfGKuVfr83oFlPLmKri1cX+Z3cJP39GXmnqkP11Gw==", - "dev": true + "version": "18.19.130", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz", + "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@fluidframework/server-memory-orderer/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "license": "MIT" }, "node_modules/@fluidframework/server-memory-orderer/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" + "uuid": "dist/esm/bin/uuid" } }, "node_modules/@fluidframework/server-services-client": { - "version": "0.1036.5001", - "resolved": "https://registry.npmjs.org/@fluidframework/server-services-client/-/server-services-client-0.1036.5001.tgz", - "integrity": "sha512-e+Zk2uPcds9yqlalAZ0PpfEAKPPUIpIoQb3YSm42ZVpAgQmLYIRqTpXrmTC7qdeQnSGFJUAliW4DfHBEwpSXlQ==", - "dependencies": { - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/gitresources": "^0.1036.5001", - "@fluidframework/protocol-base": "^0.1036.5001", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "axios": "^0.26.0", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@fluidframework/server-services-client/-/server-services-client-7.0.1.tgz", + "integrity": "sha512-39T7SZba2JdrkkOYqcGr8ZEg+SqPtxVTsHM02CI1yrvZPL78jog0iGcNRe8BrPyTCH0Xw9QOqpJND4/QbV/l4Q==", + "license": "MIT", + "dependencies": { + "@fluidframework/common-utils": "^3.1.0", + "@fluidframework/gitresources": "7.0.1", + "@fluidframework/protocol-base": "7.0.1", + "@fluidframework/protocol-definitions": "^3.2.0", + "axios": "^1.8.4", "crc-32": "1.2.0", - "debug": "^4.1.1", + "debug": "^4.3.4", "json-stringify-safe": "^5.0.1", - "jsrsasign": "^10.2.0", - "jwt-decode": "^3.0.0", - "querystring": "^0.2.0", + "jsrsasign": "^11.0.0", + "jwt-decode": "^4.0.0", "sillyname": "^0.1.0", - "uuid": "^8.3.1" + "uuid": "^11.1.0" } }, "node_modules/@fluidframework/server-services-client/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" + "uuid": "dist/esm/bin/uuid" } }, "node_modules/@fluidframework/server-services-core": { - "version": "0.1036.5001", - "resolved": "https://registry.npmjs.org/@fluidframework/server-services-core/-/server-services-core-0.1036.5001.tgz", - "integrity": "sha512-wQ0lt+iZavtR0klU9JFguMok/TqjFQYoCKosxRXdek756TglSIhzQhupKs0YFrYec1Ln2r0mhkTJLfDxkQO4Rg==", - "dev": true, + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@fluidframework/server-services-core/-/server-services-core-7.0.1.tgz", + "integrity": "sha512-5LCpUKcEaV4bFf7SkqkHv8SpHNUWacXtKNzI5JLfkTUCPdiax4tDUjaTTkrMAibrt/3q3eCdb/ZnqY7Xc4qE6A==", + "license": "MIT", "dependencies": { - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/gitresources": "^0.1036.5001", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/server-services-client": "^0.1036.5001", - "@fluidframework/server-services-telemetry": "^0.1036.5001", + "@fluidframework/common-utils": "^3.1.0", + "@fluidframework/gitresources": "7.0.1", + "@fluidframework/protocol-definitions": "^3.2.0", + "@fluidframework/server-services-client": "7.0.1", + "@fluidframework/server-services-telemetry": "7.0.1", "@types/nconf": "^0.10.2", - "@types/node": "^14.18.0", - "debug": "^4.1.1", + "@types/node": "^18.19.39", + "debug": "^4.3.4", + "events": "^3.1.0", "nconf": "^0.12.0" } }, "node_modules/@fluidframework/server-services-core/node_modules/@types/node": { - "version": "14.18.47", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.47.tgz", - "integrity": "sha512-OuJi8bIng4wYHHA3YpKauL58dZrPxro3d0tabPHyiNF8rKfGKuVfr83oFlPLmKri1cX+Z3cJP39GXmnqkP11Gw==", - "dev": true + "version": "18.19.130", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz", + "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@fluidframework/server-services-core/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "license": "MIT" }, "node_modules/@fluidframework/server-services-telemetry": { - "version": "0.1036.5001", - "resolved": "https://registry.npmjs.org/@fluidframework/server-services-telemetry/-/server-services-telemetry-0.1036.5001.tgz", - "integrity": "sha512-uV3KZVij7AIqw4AvPqqdgq73dgACIN6MFxKwQgXQL7zZO4zBd/M/vCujOxPwS6NvHgfBZnn5yAWvLX3MldywYg==", - "dev": true, + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@fluidframework/server-services-telemetry/-/server-services-telemetry-7.0.1.tgz", + "integrity": "sha512-4lF+Vhs+YMctigdEFdQ1XisuY3FmUVskpUqNI60yMVKClKlWd10zJy0j+V1enaIYP5Q4kja/LXusNuzLDrS0Dw==", + "license": "MIT", "dependencies": { - "@fluidframework/common-utils": "^0.32.2", + "@fluidframework/common-utils": "^3.1.0", "json-stringify-safe": "^5.0.1", "path-browserify": "^1.0.1", "serialize-error": "^8.1.0", - "uuid": "^8.3.1" + "uuid": "^11.1.0" } }, "node_modules/@fluidframework/server-services-telemetry/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" + "uuid": "dist/esm/bin/uuid" } }, "node_modules/@fluidframework/server-test-utils": { - "version": "0.1036.5001", - "resolved": "https://registry.npmjs.org/@fluidframework/server-test-utils/-/server-test-utils-0.1036.5001.tgz", - "integrity": "sha512-kks83OhWF8xRyoQXz7PHBPvXiCEuylCR9J/YKkQ/u0Xo2nvckEDSwWcpED08JIo7b3NXtkvd8H1BfG3UWoof+w==", - "dev": true, - "dependencies": { - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/gitresources": "^0.1036.5001", - "@fluidframework/protocol-base": "^0.1036.5001", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/server-services-client": "^0.1036.5001", - "@fluidframework/server-services-core": "^0.1036.5001", - "@fluidframework/server-services-telemetry": "^0.1036.5001", - "debug": "^4.1.1", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@fluidframework/server-test-utils/-/server-test-utils-7.0.1.tgz", + "integrity": "sha512-x6WN7pJNfjFBzCHdQKheIbIDgIb3jsi9AMx30JWPVqciBUWptMGrQK7/0Qo2URdQhzJ0A1j8jmE5ghKbGpYFYA==", + "license": "MIT", + "dependencies": { + "@fluidframework/common-utils": "^3.1.0", + "@fluidframework/gitresources": "7.0.1", + "@fluidframework/protocol-base": "7.0.1", + "@fluidframework/protocol-definitions": "^3.2.0", + "@fluidframework/server-services-client": "7.0.1", + "@fluidframework/server-services-core": "7.0.1", + "@fluidframework/server-services-telemetry": "7.0.1", + "@types/ioredis-mock": "^8.2.6", + "assert": "^2.0.0", + "debug": "^4.3.4", + "events": "^3.1.0", + "ioredis": "^5.6.1", + "ioredis-mock": "^8.9.0", "lodash": "^4.17.21", "string-hash": "^1.1.3", - "uuid": "^8.3.1" + "uuid": "^11.1.0" } }, "node_modules/@fluidframework/server-test-utils/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" + "uuid": "dist/esm/bin/uuid" } }, "node_modules/@fluidframework/shared-object-base": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/shared-object-base/-/shared-object-base-1.3.6.tgz", - "integrity": "sha512-eUMtIosNBwDJXpw69BJuOLGJw4Lf53f6sU6ZgNKU1l2C5/Ht7gG2iDEBxYnNUvVAMQprTHYt5T1qTwn8uaT+Lw==", - "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/container-definitions": "^1.3.6", - "@fluidframework/container-runtime": "^1.3.6", - "@fluidframework/container-utils": "^1.3.6", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/datastore": "^1.3.6", - "@fluidframework/datastore-definitions": "^1.3.6", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/runtime-definitions": "^1.3.6", - "@fluidframework/runtime-utils": "^1.3.6", - "@fluidframework/telemetry-utils": "^1.3.6", - "uuid": "^8.3.1" + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/shared-object-base/-/shared-object-base-2.110.0.tgz", + "integrity": "sha512-lUeyXIfV0sM5/rhCXbk9vSD4tcBiUomKXiTSwV7N7P+3rnIV2NWkdgEP+FYn0yQdMR8G0RWS6rTScW51H0EeyQ==", + "license": "MIT", + "dependencies": { + "@fluid-internal/client-utils": "~2.110.0", + "@fluidframework/container-definitions": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/datastore": "~2.110.0", + "@fluidframework/datastore-definitions": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "@fluidframework/id-compressor": "~2.110.0", + "@fluidframework/runtime-definitions": "~2.110.0", + "@fluidframework/runtime-utils": "~2.110.0", + "@fluidframework/telemetry-utils": "~2.110.0", + "uuid": "^11.1.0" } }, "node_modules/@fluidframework/shared-object-base/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" + "uuid": "dist/esm/bin/uuid" } }, "node_modules/@fluidframework/synthesize": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/synthesize/-/synthesize-1.3.6.tgz", - "integrity": "sha512-avt0K5uxvOjs1Y6XpisonkMmG3RaI901h5XfIWFlxOhkHSgeN7T3ZmTdAinlpyRv+XKHzVzN1SqaccpGeC0+lw==" + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/synthesize/-/synthesize-2.110.0.tgz", + "integrity": "sha512-KRSPMCRWJk2xe6Sd5KNYgacqK4VDvStj5bgnfPcNqE9zld7nMxmbCzsntJeS1um61X4vmgZoF6h0KPT7rKlo2A==", + "license": "MIT", + "dependencies": { + "@fluidframework/core-utils": "~2.110.0" + } }, "node_modules/@fluidframework/telemetry-utils": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/telemetry-utils/-/telemetry-utils-1.3.6.tgz", - "integrity": "sha512-9DoLzKwnELWBN2NiCJPgfj2lCER4IiHSgiBMwbLoEZ0qTqGKhWJ1+7m1PupuwGuKX1zbb9HjUNxv2ommokZcqw==", + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/telemetry-utils/-/telemetry-utils-2.110.0.tgz", + "integrity": "sha512-FzuyyKv2f2YPOUoigAnpDGbTiQykgqwTnVc3Xn4NIRhg3knkXSd9Ljx/Hy2WRBNbdAuCGWrYgMvIWkjj6OseWA==", + "license": "MIT", "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/common-utils": "^0.32.2", - "debug": "^4.1.1", - "events": "^3.1.0", - "uuid": "^8.3.1" + "@fluid-internal/client-utils": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "debug": "^4.3.4", + "uuid": "^11.1.0" } }, "node_modules/@fluidframework/telemetry-utils/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@fluidframework/test-client-utils": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/test-client-utils/-/test-client-utils-1.3.6.tgz", - "integrity": "sha512-bwF/R/dDhpjwTQPlZvy/nqYApzLaBV7abolBhB3dKDdMPEDDqhTQP3pLreY3c43c+TLvInwYZCXeruAQlItocQ==", - "dev": true, - "dependencies": { - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/test-runtime-utils": "^1.3.6", - "sillyname": "^0.1.0" + "uuid": "dist/esm/bin/uuid" } }, "node_modules/@fluidframework/test-driver-definitions": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/test-driver-definitions/-/test-driver-definitions-1.3.6.tgz", - "integrity": "sha512-GLg2bcNcAFDa2LFJ1P5SqKqfzsYKTP567ZYguhI7OOgEpzL4pVpaWVdDw/nYlBqhOOooXBLt0cR1U3rNaRn36A==", + "version": "2.0.0-rc.1.0.9", + "resolved": "https://registry.npmjs.org/@fluidframework/test-driver-definitions/-/test-driver-definitions-2.0.0-rc.1.0.9.tgz", + "integrity": "sha512-7IGZDKA5241iHorW/QhLLvJOw6a6eKSv+G6nZWiejk08qvdpqcW7tFgPtdvXDoe28Or5Z+p2p3/c8D4qilDqag==", "dev": true, + "license": "MIT", "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/driver-definitions": "^1.3.6", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "uuid": "^8.3.1" - } - }, - "node_modules/@fluidframework/test-driver-definitions/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" + "@fluidframework/core-interfaces": ">=2.0.0-rc.1.0.9 <2.0.0-rc.1.1.0", + "@fluidframework/driver-definitions": ">=2.0.0-rc.1.0.9 <2.0.0-rc.1.1.0", + "@fluidframework/protocol-definitions": "^3.1.0", + "uuid": "^9.0.0" } }, - "node_modules/@fluidframework/test-drivers": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/test-drivers/-/test-drivers-1.3.6.tgz", - "integrity": "sha512-MtrbiZ6bpIY7XrNzJLp1J4OEc/tvWUsK5KsXU5Rz10udLWq6k7cQGnDbJmWm9GLEpwLqSx0Uet3bA7vDX9/Aew==", - "dev": true, - "dependencies": { - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/driver-definitions": "^1.3.6", - "@fluidframework/driver-utils": "^1.3.6", - "@fluidframework/local-driver": "^1.3.6", - "@fluidframework/odsp-doclib-utils": "^1.3.6", - "@fluidframework/odsp-driver": "^1.3.6", - "@fluidframework/odsp-driver-definitions": "^1.3.6", - "@fluidframework/odsp-urlresolver": "^1.3.6", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/routerlicious-driver": "^1.3.6", - "@fluidframework/server-local-server": "^0.1036.5001", - "@fluidframework/test-driver-definitions": "^1.3.6", - "@fluidframework/test-pairwise-generator": "^1.3.6", - "@fluidframework/test-runtime-utils": "^1.3.6", - "@fluidframework/tinylicious-driver": "^1.3.6", - "@fluidframework/tool-utils": "^1.3.6", - "axios": "^0.26.0", - "semver": "^7.3.4", - "uuid": "^8.3.1" - } - }, - "node_modules/@fluidframework/test-drivers/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "node_modules/@fluidframework/test-driver-definitions/node_modules/@fluidframework/core-interfaces": { + "version": "2.0.0-rc.1.0.9", + "resolved": "https://registry.npmjs.org/@fluidframework/core-interfaces/-/core-interfaces-2.0.0-rc.1.0.9.tgz", + "integrity": "sha512-o7J+UNzfSU7ImQmT96TK27UJ6o2LB1sKBWxyaAsl5FMicBESIX6669yXE/jggBXoDZndUZfISBXRukDjhiQy0w==", "dev": true, - "bin": { - "uuid": "dist/bin/uuid" - } + "license": "MIT" }, - "node_modules/@fluidframework/test-pairwise-generator": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/test-pairwise-generator/-/test-pairwise-generator-1.3.6.tgz", - "integrity": "sha512-nb+o0h275URMAaVp98ozVjAWKwdf2fZcWtRN2rslrtHtaI7mFFA6uwl3qEeGWWEQLZ+kGs9LYhmZjl3vl7aBHw==", + "node_modules/@fluidframework/test-driver-definitions/node_modules/@fluidframework/driver-definitions": { + "version": "2.0.0-rc.1.0.9", + "resolved": "https://registry.npmjs.org/@fluidframework/driver-definitions/-/driver-definitions-2.0.0-rc.1.0.9.tgz", + "integrity": "sha512-kefQ7jZQWxloRymUaZN5dqHx2CPnNVxAZS9H6wYitVstK4TN2KiCKGRm3kTXGyy2zGrF1L115+b9C8pH/8O6Ww==", "dev": true, + "license": "MIT", "dependencies": { - "@fluidframework/common-utils": "^0.32.2", - "random-js": "^1.0.8" + "@fluidframework/core-interfaces": ">=2.0.0-rc.1.0.9 <2.0.0-rc.1.1.0", + "@fluidframework/protocol-definitions": "^3.1.0" } }, "node_modules/@fluidframework/test-runtime-utils": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/test-runtime-utils/-/test-runtime-utils-1.3.6.tgz", - "integrity": "sha512-OoYH8Ht2nIqEwcnbz4Cg4sGk0HTkKg0+dNmZ7aP4qzctibKdNwObmypdia3MMmx16hpQRExhzO1d0ut/fRzLkA==", - "dev": true, - "dependencies": { - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/container-definitions": "^1.3.6", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/datastore-definitions": "^1.3.6", - "@fluidframework/driver-definitions": "^1.3.6", - "@fluidframework/driver-utils": "^1.3.6", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/routerlicious-driver": "^1.3.6", - "@fluidframework/runtime-definitions": "^1.3.6", - "@fluidframework/runtime-utils": "^1.3.6", - "@fluidframework/telemetry-utils": "^1.3.6", - "axios": "^0.26.0", - "events": "^3.1.0", - "jsrsasign": "^10.5.25", - "uuid": "^8.3.1" + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/test-runtime-utils/-/test-runtime-utils-2.110.0.tgz", + "integrity": "sha512-ali5vagyjK8ByUSe+4MYwOYV4LIfVIhc+6aDWcEvzEYuNnR17gKZDeVbYLzDB6s+IIRxZ7+HxiUH8TTRKBJtLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@fluid-internal/client-utils": "~2.110.0", + "@fluidframework/container-definitions": "~2.110.0", + "@fluidframework/container-runtime-definitions": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/datastore-definitions": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "@fluidframework/driver-utils": "~2.110.0", + "@fluidframework/id-compressor": "~2.110.0", + "@fluidframework/routerlicious-driver": "~2.110.0", + "@fluidframework/runtime-definitions": "~2.110.0", + "@fluidframework/runtime-utils": "~2.110.0", + "@fluidframework/telemetry-utils": "~2.110.0", + "jsrsasign": "^11.1.1", + "uuid": "^11.1.0" } }, "node_modules/@fluidframework/test-runtime-utils/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" + "uuid": "dist/esm/bin/uuid" } }, "node_modules/@fluidframework/test-utils": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/test-utils/-/test-utils-1.3.6.tgz", - "integrity": "sha512-lvnFjHqXpBJ+cCWo5Q1yQjeMN/dkFl2vsPT8+95uwuUDtz+p7com7XlMXfhbR+4jrSEvZWXh55J4jRTNGsYZvQ==", - "dev": true, - "dependencies": { - "@fluidframework/aqueduct": "^1.3.6", - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/container-definitions": "^1.3.6", - "@fluidframework/container-loader": "^1.3.6", - "@fluidframework/container-runtime": "^1.3.6", - "@fluidframework/container-runtime-definitions": "^1.3.6", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/datastore": "^1.3.6", - "@fluidframework/datastore-definitions": "^1.3.6", - "@fluidframework/driver-definitions": "^1.3.6", - "@fluidframework/driver-utils": "^1.3.6", - "@fluidframework/local-driver": "^1.3.6", - "@fluidframework/map": "^1.3.6", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/request-handler": "^1.3.6", - "@fluidframework/routerlicious-driver": "^1.3.6", - "@fluidframework/runtime-definitions": "^1.3.6", - "@fluidframework/runtime-utils": "^1.3.6", - "@fluidframework/telemetry-utils": "^1.3.6", - "@fluidframework/test-driver-definitions": "^1.3.6", - "@fluidframework/test-runtime-utils": "^1.3.6", - "debug": "^4.1.1", - "uuid": "^8.3.1" + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/test-utils/-/test-utils-2.110.0.tgz", + "integrity": "sha512-kbdTOIEboxIMazIYKeHCp6kHzegYY4jc7sYtNVEeAoCDwwZowaESkBe/e81NqKyv+MiNVacztH2kx6cghKaW2w==", + "license": "MIT", + "dependencies": { + "@fluid-internal/test-driver-definitions": "~2.110.0", + "@fluidframework/container-definitions": "~2.110.0", + "@fluidframework/container-loader": "~2.110.0", + "@fluidframework/container-runtime": "~2.110.0", + "@fluidframework/container-runtime-definitions": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/datastore": "~2.110.0", + "@fluidframework/datastore-definitions": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "@fluidframework/driver-utils": "~2.110.0", + "@fluidframework/local-driver": "~2.110.0", + "@fluidframework/map": "~2.110.0", + "@fluidframework/odsp-driver": "~2.110.0", + "@fluidframework/request-handler": "~2.110.0", + "@fluidframework/routerlicious-driver": "~2.110.0", + "@fluidframework/runtime-definitions": "~2.110.0", + "@fluidframework/runtime-utils": "~2.110.0", + "@fluidframework/shared-object-base": "~2.110.0", + "@fluidframework/telemetry-utils": "~2.110.0", + "best-random": "^1.0.0", + "debug": "^4.3.4", + "uuid": "^11.1.0" } }, "node_modules/@fluidframework/test-utils/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@fluidframework/test-version-utils": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/test-version-utils/-/test-version-utils-1.3.6.tgz", - "integrity": "sha512-/E2HsApwu/AOnQXePOQUiLZIE/N97q6mtta/1ThYPk7NqINFKTEzhVefPXh1m+5dnMCFfjhKz+BC2gpMws+cmQ==", - "dev": true, - "dependencies": { - "@fluidframework/aqueduct": "^1.3.6", - "@fluidframework/cell": "^1.3.6", - "@fluidframework/common-definitions": "^0.20.1", - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/container-definitions": "^1.3.6", - "@fluidframework/container-loader": "^1.3.6", - "@fluidframework/container-runtime": "^1.3.6", - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/counter": "^1.3.6", - "@fluidframework/datastore-definitions": "^1.3.6", - "@fluidframework/driver-definitions": "^1.3.6", - "@fluidframework/driver-utils": "^1.3.6", - "@fluidframework/ink": "^1.3.6", - "@fluidframework/map": "^1.3.6", - "@fluidframework/matrix": "^1.3.6", - "@fluidframework/mocha-test-setup": "^1.3.6", - "@fluidframework/ordered-collection": "^1.3.6", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/register-collection": "^1.3.6", - "@fluidframework/runtime-definitions": "^1.3.6", - "@fluidframework/sequence": "^1.3.6", - "@fluidframework/test-driver-definitions": "^1.3.6", - "@fluidframework/test-drivers": "^1.3.6", - "@fluidframework/test-utils": "^1.3.6", - "nconf": "^0.11.4", - "proper-lockfile": "^4.1.2", - "semver": "^7.3.4" - } - }, - "node_modules/@fluidframework/test-version-utils/node_modules/async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==", - "dev": true - }, - "node_modules/@fluidframework/test-version-utils/node_modules/nconf": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/nconf/-/nconf-0.11.4.tgz", - "integrity": "sha512-YaDR846q11JnG1vTrhJ0QIlhiGY6+W1bgWtReG9SS3vkTl3AoNwFvUItdhG6/ZjGCfWpUVuRTNEBTDAQ3nWhGw==", - "dev": true, - "dependencies": { - "async": "^1.4.0", - "ini": "^2.0.0", - "secure-keys": "^1.0.0", - "yargs": "^16.1.1" - }, - "engines": { - "node": ">= 0.4.0" + "uuid": "dist/esm/bin/uuid" } }, - "node_modules/@fluidframework/tinylicious-driver": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/tinylicious-driver/-/tinylicious-driver-1.3.6.tgz", - "integrity": "sha512-ZV6HZ1Lxnl0WFX6ajg0vpG5bCpMK21cUSI7QHteyXR76APqodu3HnMksEIuA1IgxCAW/o5n/eN02hY36yz8ANg==", - "dev": true, + "node_modules/@fluidframework/tree": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/tree/-/tree-2.110.0.tgz", + "integrity": "sha512-fWn9los6yJALYVwCSzQtoeBz6k5vjuUn99bVpXI9TGEgct8FamVOCIB3Je6RZC7t1Oc6LJzvNXGnGfz4+jee1w==", + "license": "MIT", "dependencies": { - "@fluidframework/core-interfaces": "^1.3.6", - "@fluidframework/driver-definitions": "^1.3.6", - "@fluidframework/driver-utils": "^1.3.6", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "@fluidframework/routerlicious-driver": "^1.3.6", - "@fluidframework/server-services-client": "^0.1036.5001", - "jsrsasign": "^10.5.25", - "uuid": "^8.3.1" - } - }, - "node_modules/@fluidframework/tinylicious-driver/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, + "@fluid-internal/client-utils": "~2.110.0", + "@fluidframework/container-runtime": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/datastore-definitions": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "@fluidframework/id-compressor": "~2.110.0", + "@fluidframework/runtime-definitions": "~2.110.0", + "@fluidframework/runtime-utils": "~2.110.0", + "@fluidframework/shared-object-base": "~2.110.0", + "@fluidframework/telemetry-utils": "~2.110.0", + "@fluidframework/type-factory": "~2.110.0", + "@sinclair/typebox": "^0.34.13", + "@tylerbu/sorted-btree-es6": "^2.1.1", + "semver-ts": "^1.0.3", + "tslib": "^2.8.1", + "uuid": "^11.1.0" + } + }, + "node_modules/@fluidframework/tree/node_modules/uuid": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@fluidframework/tool-utils": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/tool-utils/-/tool-utils-1.3.6.tgz", - "integrity": "sha512-IRrUPE4gadtCLUCCoUmQNVoObdBdb6/myfiaRmTDZnLguO20OUrPvYrJSF0d2pYYy5jQgJy/mN+nDrWtFhno7Q==", - "dev": true, - "dependencies": { - "@fluidframework/common-utils": "^0.32.2", - "@fluidframework/odsp-doclib-utils": "^1.3.6", - "@fluidframework/protocol-base": "^0.1036.5001", - "@fluidframework/protocol-definitions": "^0.1028.2000", - "async-mutex": "^0.3.1", - "debug": "^4.1.1", - "jwt-decode": "^2.2.0", - "proper-lockfile": "^4.1.2" + "uuid": "dist/esm/bin/uuid" } }, - "node_modules/@fluidframework/tool-utils/node_modules/jwt-decode": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-2.2.0.tgz", - "integrity": "sha512-86GgN2vzfUu7m9Wcj63iUkuDzFNYFVmjeDm2GzWpUk+opB0pEpMsw6ePCMrhYkumz2C1ihqtZzOMAg7FiXcNoQ==", - "dev": true - }, - "node_modules/@fluidframework/view-interfaces": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@fluidframework/view-interfaces/-/view-interfaces-1.3.6.tgz", - "integrity": "sha512-QEBEPmJdNCO7BdCjUaFxA32fjH91LePRs2xMV5iK8KRQwkyYnp4kRa3nKD3Iv2ezYKG+MvtAIDmUvfzICwWxUA==", + "node_modules/@fluidframework/type-factory": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/@fluidframework/type-factory/-/type-factory-2.110.0.tgz", + "integrity": "sha512-4nHB986EEQMrkFkx+/DvAr1tHKFJ+K6R3Cz5GQvIrookbtW2Po4BZfs50iO95LlT3qiMrfKIvdq4v7Xz+S+9Og==", + "license": "MIT", "dependencies": { - "@fluidframework/core-interfaces": "^1.3.6" + "@fluidframework/telemetry-utils": "~2.110.0" } }, "node_modules/@griffel/core": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@griffel/core/-/core-1.11.0.tgz", - "integrity": "sha512-3jlrsJVbNC0avRMfNGWmbklptmtH5s63Gt/xa0zY6+Oa3kU/StNAu+d0LqLChb5egwXrisQIeC+tzzJ+YozGjg==", + "version": "1.21.2", + "resolved": "https://registry.npmjs.org/@griffel/core/-/core-1.21.2.tgz", + "integrity": "sha512-vDvEdbIe7OhU15UkvUHe+Ut2sgCZ5PBj/RYLFwjUtkXS4ewNK9P6b4YRFNI2zgaNYI7GOuZqG7DLyaQbUP3+jg==", + "license": "MIT", "dependencies": { "@emotion/hash": "^0.9.0", - "csstype": "^3.1.2", + "@griffel/style-types": "^1.4.2", + "csstype": "^3.2.3", "rtl-css-js": "^1.16.1", - "stylis": "^4.0.13", + "stylis": "^4.4.0", "tslib": "^2.1.0" } }, "node_modules/@griffel/react": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@griffel/react/-/react-1.5.7.tgz", - "integrity": "sha512-b9/LkkuO512O268jqRpJPso9ROng/kqh81YSTJUL13tT4qPZQnvrdiwoP7ZeqXbG0zzZHLZ3tWUZrCDOl549OQ==", + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/@griffel/react/-/react-1.7.4.tgz", + "integrity": "sha512-XsB+YOC4MOBg6GF5CJWJLf8ZI2AtXE8EvQdwJEmFNKX0cQu/An0azl3v9+sjA73zsIG2Wayo2pkT0JANYnKauA==", + "license": "MIT", "dependencies": { - "@griffel/core": "^1.11.0", + "@griffel/core": "^1.21.2", "tslib": "^2.1.0" }, "peerDependencies": { - "react": ">=16.8.0 <19.0.0" + "react": ">=16.14.0 <20.0.0" + } + }, + "node_modules/@griffel/style-types": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@griffel/style-types/-/style-types-1.4.2.tgz", + "integrity": "sha512-MsSghfpyxR2MpTrYdcCozISsSLkmFjNw94wNPi4bDBRLW8W43718W/ZjmUdVkoM0KXMtJPYuEkx8Mzibqb03qA==", + "license": "MIT", + "dependencies": { + "csstype": "^3.2.3" + } + }, + "node_modules/@hapi/address": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@hapi/address/-/address-5.1.1.tgz", + "integrity": "sha512-A+po2d/dVoY7cYajycYI43ZbYMXukuopIsqCjh5QzsBCipDtdofHntljDlpccMjIfTy6UOkg+5KPriwYch2bXA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^11.0.2" + }, + "engines": { + "node": ">=14.0.0" } }, + "node_modules/@hapi/formula": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@hapi/formula/-/formula-3.0.2.tgz", + "integrity": "sha512-hY5YPNXzw1He7s0iqkRQi+uMGh383CGdyyIGYtB+W5N3KHPXoqychklvHhKCC9M3Xtv0OCs/IHw+r4dcHtBYWw==", + "dev": true, + "license": "BSD-3-Clause" + }, "node_modules/@hapi/hoek": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", - "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", - "dev": true + "version": "11.0.7", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-11.0.7.tgz", + "integrity": "sha512-HV5undWkKzcB4RZUusqOpcgxOaq6VOAH7zhhIr2g3G8NF/MlFO75SjOr2NfuSx0Mh40+1FqCkagKLJRykUWoFQ==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/pinpoint": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@hapi/pinpoint/-/pinpoint-2.0.1.tgz", + "integrity": "sha512-EKQmr16tM8s16vTT3cA5L0kZZcTMU5DUOZTuvpnY738m+jyP3JIUj+Mm1xc1rsLkGBQ/gVnfKYPwOmPg1tUR4Q==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/tlds": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@hapi/tlds/-/tlds-1.1.7.tgz", + "integrity": "sha512-MgNjRwy9Ti92yVAixLmDc8dd1bJIKwO9qlWCfFQRwRmUEDPQHYn4G6hwPFvFGUTzAa0FsS+inMjLin7GnyBRhA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=14.0.0" + } }, "node_modules/@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-6.0.2.tgz", + "integrity": "sha512-KR3rD5inZbGMrHmgPxsJ9dbi6zEK+C3ZwUwTa+eMwWLz7oijWUTWD2pMSNNYJAU6Qq+65NkxXjqHr/7LM2Xkqg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "@hapi/hoek": "^9.0.0" + "@hapi/hoek": "^11.0.2" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", "minimatch": "^3.0.5" }, "engines": { "node": ">=10.10.0" } }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=12.22" }, @@ -3588,16 +4622,31 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@ioredis/as-callback": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@ioredis/as-callback/-/as-callback-3.0.0.tgz", + "integrity": "sha512-Kqv1rZ3WbgOrS+hgzJ5xG5WQuhvzzSTRYvNeyPMLOAM78MHSnuKI20JeJGbpuAt//LCuP0vsexZcorqW7kWhJg==", + "license": "MIT" + }, + "node_modules/@ioredis/commands": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.10.0.tgz", + "integrity": "sha512-UmeW7z4LfctwoQ5wkhVzgq8tXkreED2xZGpX+Bg+zA+WJFZCT6c062AfCK/Dfk81xZnnwdhJCUMkitihRaoC2Q==", + "license": "MIT" }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, + "license": "ISC", "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", @@ -3614,6 +4663,7 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, + "license": "MIT", "dependencies": { "sprintf-js": "~1.0.2" } @@ -3623,6 +4673,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -3632,10 +4683,11 @@ } }, "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -3649,6 +4701,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -3661,6 +4714,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -3676,6 +4730,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -3688,139 +4743,294 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.6.tgz", + "integrity": "sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, + "node_modules/@jest/diff-sequences": { + "version": "30.4.0", + "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.4.0.tgz", + "integrity": "sha512-zOpzlfUs45l6u7jm39qr87JCHUDsaeCtvL+kQe/Vn9jSnRB4/5IPXISm0h9I1vZW/o00Kn4UTJ2MOlhnUGwv3g==", + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, "node_modules/@jest/environment": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", - "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^27.5.1" + "jest-mock": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/environment/node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/environment/node_modules/@jest/types": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", - "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, + "license": "MIT", "dependencies": { + "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", - "@types/yargs": "^16.0.0", + "@types/yargs": "^17.0.8", "chalk": "^4.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/environment/node_modules/@types/yargs": { - "version": "16.0.5", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.5.tgz", - "integrity": "sha512-AxO/ADJOBFJScHbWhq2xAhlWP24rY4aCEG/NFaMvbT3X2MgRsLjhjQwsn0Zi5zn0LG9jUhCCZMeX9Dkuw6k+vQ==", + "node_modules/@jest/environment/node_modules/@sinclair/typebox": { + "version": "0.27.10", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz", + "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==", "dev": true, - "dependencies": { - "@types/yargs-parser": "*" - } + "license": "MIT" }, - "node_modules/@jest/expect-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz", - "integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==", - "dependencies": { - "jest-get-type": "^29.4.3" + "node_modules/@jest/environment/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/environment/node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/@jest/environment/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/environment/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@jest/expect-utils": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.4.1.tgz", + "integrity": "sha512-ZBn5CglH8fBsQsvs4VWNzD4aWfUYks+IdOOQU3MEK71ol/BcVm+P+rtb1KpiFBpSWSCE27uOahyyf1vfqOVbcQ==", + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, "node_modules/@jest/fake-timers": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", - "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/types": "^27.5.1", - "@sinonjs/fake-timers": "^8.0.1", + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1" + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers/node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/fake-timers/node_modules/@jest/types": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", - "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, + "license": "MIT", "dependencies": { + "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", - "@types/yargs": "^16.0.0", + "@types/yargs": "^17.0.8", "chalk": "^4.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/fake-timers/node_modules/@types/yargs": { - "version": "16.0.5", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.5.tgz", - "integrity": "sha512-AxO/ADJOBFJScHbWhq2xAhlWP24rY4aCEG/NFaMvbT3X2MgRsLjhjQwsn0Zi5zn0LG9jUhCCZMeX9Dkuw6k+vQ==", + "node_modules/@jest/fake-timers/node_modules/@sinclair/typebox": { + "version": "0.27.10", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz", + "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==", "dev": true, - "dependencies": { - "@types/yargs-parser": "*" + "license": "MIT" + }, + "node_modules/@jest/fake-timers/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/fake-timers/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" } }, "node_modules/@jest/fake-timers/node_modules/jest-message-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", - "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.5.1", + "@jest/types": "^29.6.3", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^27.5.1", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers/node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/fake-timers/node_modules/jest-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", - "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/types": "^27.5.1", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -3828,105 +5038,167 @@ "picomatch": "^2.2.3" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/schemas": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", - "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", + "node_modules/@jest/fake-timers/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@jest/fake-timers/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "license": "MIT", "dependencies": { - "@sinclair/typebox": "^0.25.16" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/@jest/fake-timers/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jest/get-type": { + "version": "30.1.0", + "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.1.0.tgz", + "integrity": "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==", + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/pattern": { + "version": "30.4.0", + "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.4.0.tgz", + "integrity": "sha512-RAWn3+f9u8BsHijKJ71uHcFp6vmyEt6VvoWXkl6hKF3qVIuWNmudVjg12DlBPGup/frIl5UcUlH5HfEuvHpEXg==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-regex-util": "30.4.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/schemas": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.4.1.tgz", + "integrity": "sha512-i6b4qw5qnP8c5FEeBJg/uZQ4ddrkN6Ca8qISJh0pr7a5hfn3h3v5x60BEbOC7OYAGZNMs1LfFLwnW2CuK8F57Q==", + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, "node_modules/@jest/types": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", - "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.4.1.tgz", + "integrity": "sha512-f1x/vJXIfjOlEmejYpbkbgw1gOqpPECwMvMEtBqe47j7H2Hg8h8w3o3ikhSXq3MI15kg+oQ0exWO0uCtTNJLoQ==", + "license": "MIT", "dependencies": { - "@jest/schemas": "^29.4.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", + "@jest/pattern": "30.4.0", + "@jest/schemas": "30.4.1", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", "dev": true, - "engines": { - "node": ">=6.0.0" + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/source-map": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.3.tgz", - "integrity": "sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==", + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, "node_modules/@juggle/resize-observer": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.4.0.tgz", - "integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==" + "integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==", + "license": "Apache-2.0" + }, + "node_modules/@live-share-private/test-utils": { + "resolved": "internal/test-utils", + "link": true }, "node_modules/@microsoft/01.dice-roller": { "resolved": "samples/javascript/01.dice-roller", @@ -4004,23 +5276,107 @@ "resolved": "packages/live-share-react", "link": true }, - "node_modules/@microsoft/live-share-turbo": { - "resolved": "packages/live-share-turbo", - "link": true - }, "node_modules/@microsoft/teams-js": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/@microsoft/teams-js/-/teams-js-2.16.0.tgz", - "integrity": "sha512-3X9y6iG9P2K/lmrdGaGH41O5cnEHJ6mU4Yl+B0ljwwzW4SBHpjyr66YS1WvC+WCvpaj3ghQfPgFRIE2qXFgWeA==", + "version": "2.53.1", + "resolved": "https://registry.npmjs.org/@microsoft/teams-js/-/teams-js-2.53.1.tgz", + "integrity": "sha512-GXVtIGMl9jdXBQybVSYSzaUCDzoDJDfG02xXhxuKCJqCvPSacXtFslZINPpvOk22r+ajj4+mBGyuI4sI3iRYUg==", + "license": "MIT", "dependencies": { + "base64-js": "^1.3.1", "debug": "^4.3.3" } }, + "node_modules/@microsoft/tsdoc": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.15.1.tgz", + "integrity": "sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@microsoft/tsdoc-config": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.17.1.tgz", + "integrity": "sha512-UtjIFe0C6oYgTnad4q1QP4qXwLhe6tIpNTRStJ2RZEPIkqQPREAwE5spzVxsdn9UaEMUqhh0AqSx3X4nWAKXWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@microsoft/tsdoc": "0.15.1", + "ajv": "~8.12.0", + "jju": "~1.4.0", + "resolve": "~1.22.2" + } + }, + "node_modules/@microsoft/tsdoc-config/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@microsoft/tsdoc-config/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/@microsoft/tsdoc-config/node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.6.tgz", + "integrity": "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.3" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -4034,6 +5390,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -4043,6 +5400,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -4051,35 +5409,46 @@ "node": ">= 8" } }, + "node_modules/@package-json/types": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@package-json/types/-/types-0.0.12.tgz", + "integrity": "sha512-uu43FGU34B5VM9mCNjXCwLaGHYjXdNincqKLaraaCW+7S2+SmiBg1Nv8bPnmschrIfZmfKNY9f3fC376MRrObw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@pkgr/core": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.3.6.tgz", + "integrity": "sha512-SEeaJLb3qBNF/OaXnaR1NmmBbFYk1zC0ZH/52fATcRPLFg/p791YrcyFFy44Bo9sLaGuSuLp5Q6axbb/O+v/RA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, "node_modules/@puppeteer/browsers": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-1.3.0.tgz", - "integrity": "sha512-an3QdbNPkuU6qpxpbssxAbjRLJcF+eP4L8UqIY3+6n0sbaVxw5pz7PiCLy9g32XEZuoamUlV5ZQPnA6FxvkIHA==", + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.13.2.tgz", + "integrity": "sha512-5EUZSUIc37H6aIXyWO0Z4y8NlF8NnjgmqeQgOGiswAU7pY0HOo16ho4+alIWmSfdZnjqBRawMsP3I5YqLSn6kw==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "debug": "4.3.4", - "extract-zip": "2.0.1", - "http-proxy-agent": "5.0.0", - "https-proxy-agent": "5.0.1", - "progress": "2.0.3", - "proxy-from-env": "1.1.0", - "tar-fs": "2.1.1", - "unbzip2-stream": "1.4.3", - "yargs": "17.7.1" + "debug": "^4.4.3", + "extract-zip": "^2.0.1", + "progress": "^2.0.3", + "proxy-agent": "^6.5.0", + "semver": "^7.7.4", + "tar-fs": "^3.1.1", + "yargs": "^17.7.2" }, "bin": { "browsers": "lib/cjs/main-cli.js" }, "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "typescript": ">= 4.7.4" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=18" } }, "node_modules/@puppeteer/browsers/node_modules/cliui": { @@ -4087,6 +5456,7 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -4097,10 +5467,11 @@ } }, "node_modules/@puppeteer/browsers/node_modules/yargs": { - "version": "17.7.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", - "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", + "version": "17.7.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz", + "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==", "dev": true, + "license": "MIT", "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -4119,2262 +5490,2366 @@ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, + "license": "ISC", "engines": { "node": ">=12" } }, "node_modules/@remix-run/router": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.6.2.tgz", - "integrity": "sha512-LzqpSrMK/3JBAVBI9u3NWtOhWNw5AMQfrUFYB0+bDHTSw17z++WJLsPsxAuK+oSddsxk4d7F/JcdDPM1M5YAhA==", + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.3.tgz", + "integrity": "sha512-4An71tdz9X8+3sI4Qqqd2LWd9vS39J7sqd9EU4Scw7TJE/qB10Flv/UuqbPVgfQV9XoK8Np6jNquZitnZq5i+Q==", + "license": "MIT", "engines": { - "node": ">=14" + "node": ">=14.0.0" } }, - "node_modules/@sideway/address": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", - "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz", + "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==", "dev": true, - "dependencies": { - "@hapi/hoek": "^9.0.0" - } - }, - "node_modules/@sideway/formula": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", - "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", - "dev": true - }, - "node_modules/@sideway/pinpoint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", - "dev": true - }, - "node_modules/@sinclair/typebox": { - "version": "0.25.24", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", - "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==" + "license": "MIT" }, - "node_modules/@sinonjs/commons": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", - "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.2.tgz", + "integrity": "sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } + "license": "MIT", + "optional": true, + "os": [ + "android" + ] }, - "node_modules/@sinonjs/fake-timers": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", - "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.2.tgz", + "integrity": "sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.7.0" - } - }, - "node_modules/@socket.io/component-emitter": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", - "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" - }, - "node_modules/@swc/helpers": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", - "integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==", - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@testing-library/dom": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.0.tgz", - "integrity": "sha512-Dffe68pGwI6WlLRYR2I0piIkyole9cSBH5jGQKCGMRpHW5RHCqAUaqc2Kv0tUyd4dU4DLPKhJIjyKOnjv4tuUw==", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "^5.0.0", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.5.0", - "pretty-format": "^27.0.2" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@testing-library/jest-dom": { - "version": "5.16.5", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz", - "integrity": "sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA==", - "dependencies": { - "@adobe/css-tools": "^4.0.1", - "@babel/runtime": "^7.9.2", - "@types/testing-library__jest-dom": "^5.9.1", - "aria-query": "^5.0.0", - "chalk": "^3.0.0", - "css.escape": "^1.5.1", - "dom-accessibility-api": "^0.5.6", - "lodash": "^4.17.15", - "redent": "^3.0.0" - }, - "engines": { - "node": ">=8", - "npm": ">=6", - "yarn": ">=1" - } - }, - "node_modules/@testing-library/jest-dom/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@testing-library/react": { - "version": "13.4.0", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-13.4.0.tgz", - "integrity": "sha512-sXOGON+WNTh3MLE9rve97ftaZukN3oNf2KjDy7YTx6hcTO2uuLHuCGynMDhFwGw/jYf4OJ2Qk0i4i79qMNNkyw==", - "dependencies": { - "@babel/runtime": "^7.12.5", - "@testing-library/dom": "^8.5.0", - "@types/react-dom": "^18.0.0" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - } - }, - "node_modules/@testing-library/react/node_modules/@testing-library/dom": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.20.0.tgz", - "integrity": "sha512-d9ULIT+a4EXLX3UU8FBjauG9NnsZHkHztXoIcTsOKoOw030fyjheN9svkTULjJxtYag9DZz5Jz5qkWZDPxTFwA==", - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "^5.0.0", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.4.4", - "pretty-format": "^27.0.2" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@testing-library/user-event": { - "version": "14.4.3", - "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.4.3.tgz", - "integrity": "sha512-kCUc5MEwaEMakkO5x7aoD+DLi02ehmEM2QCGWvNqAS1dV/fAvORWEjnjsEIvml59M7Y5kCkWN6fCCyPOe8OL6Q==", - "engines": { - "node": ">=12", - "npm": ">=6" - }, - "peerDependencies": { - "@testing-library/dom": ">=7.21.4" - } - }, - "node_modules/@tiny-calc/nano": { - "version": "0.0.0-alpha.5", - "resolved": "https://registry.npmjs.org/@tiny-calc/nano/-/nano-0.0.0-alpha.5.tgz", - "integrity": "sha512-Hs37tz9ZtvK21/5s4tjt5RBa/PFHKYS0AzvdxiXuSd3+AKQN2ygxw7uwD9j0DIG9qONddg1vIASO77JIGyZzyw==", - "dev": true + "license": "MIT", + "optional": true, + "os": [ + "android" + ] }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.2.tgz", + "integrity": "sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==", + "cpu": [ + "arm64" + ], "dev": true, - "engines": { - "node": ">= 10" - } + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@types/aria-query": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.1.tgz", - "integrity": "sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==" + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.2.tgz", + "integrity": "sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@types/assert": { - "version": "1.5.6", - "resolved": "https://registry.npmjs.org/@types/assert/-/assert-1.5.6.tgz", - "integrity": "sha512-Y7gDJiIqb9qKUHfBQYOWGngUpLORtirAVPuj/CWJrU2C6ZM4/y3XLwuwfGMF8s7QzW746LQZx23m0+1FSgjfug==", - "dev": true + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.2.tgz", + "integrity": "sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] }, - "node_modules/@types/babylonjs": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/babylonjs/-/babylonjs-2.4.1.tgz", - "integrity": "sha512-vt6db2PxisxsnLvL5holHLV9vMJzELAhFq54syX/tKncTmjeraQSR1W20j9/KYLEpAFU18u76rK8utb8JlUrtQ==", - "deprecated": "This is a stub types definition for BabylonJS (http://www.babylonjs.com/). BabylonJS provides its own type definitions, so you don't need @types/babylonjs installed!", + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.2.tgz", + "integrity": "sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "babylonjs": "*" - } + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] }, - "node_modules/@types/debug": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", - "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==", + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.2.tgz", + "integrity": "sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "@types/ms": "*" - } + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/double-ended-queue": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@types/double-ended-queue/-/double-ended-queue-2.1.2.tgz", - "integrity": "sha512-iAjbBa3X4UQtYxcCsAr0YaZMRwyC79q4KHui0XtEN7GGLJA4fzD116KUYXXZKskaOYSchnaOFT/a8zSlEx3P9Q==", - "dev": true + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.2.tgz", + "integrity": "sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/eslint": { - "version": "8.37.0", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.37.0.tgz", - "integrity": "sha512-Piet7dG2JBuDIfohBngQ3rCt7MgO9xCO4xIMKxBThCq5PNRB91IjlJ10eJVwfoNtvTErmxLzwBZ7rHZtbOMmFQ==", + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.2.tgz", + "integrity": "sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==", + "cpu": [ + "arm64" + ], "dev": true, - "peer": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.2.tgz", + "integrity": "sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==", + "cpu": [ + "arm64" + ], "dev": true, - "peer": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/estree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", - "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.2.tgz", + "integrity": "sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==", + "cpu": [ + "loong64" + ], "dev": true, - "peer": true + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/events": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", - "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==" + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.2.tgz", + "integrity": "sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==" - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/jest": { - "version": "29.5.1", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.1.tgz", - "integrity": "sha512-tEuVcHrpaixS36w7hpsfLBLpjtMRJUE09/MHXn923LOVojDwyC14cWcfc0rDs0VEfUyYmt/+iX1kxxp+gZMcaQ==", - "dependencies": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" - } - }, - "node_modules/@types/jest/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@types/jest/node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", - "dependencies": { - "@jest/schemas": "^29.4.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@types/jest/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.2.tgz", + "integrity": "sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.2.tgz", + "integrity": "sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.2.tgz", + "integrity": "sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==", + "cpu": [ + "riscv64" + ], "dev": true, - "optional": true + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/lodash": { - "version": "4.14.194", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.194.tgz", - "integrity": "sha512-r22s9tAS7imvBt2lyHC9B8AGwWnXaYb1tY09oyLkXDs4vArpYJzw09nj8MLx5VfciBPGIb+ZwG0ssYnEPJxn/g==", - "dev": true + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.2.tgz", + "integrity": "sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/mocha": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.1.tgz", - "integrity": "sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==", - "dev": true + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.2.tgz", + "integrity": "sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/ms": { - "version": "0.7.31", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", - "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==", - "dev": true + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.2.tgz", + "integrity": "sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/nconf": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/@types/nconf/-/nconf-0.10.3.tgz", - "integrity": "sha512-leyIuBk/rMIp9114FlPRkc/cQG+/JzCz1Afx3BD+CwK2ep3ZRxoC843V1rqnE2pC/jRRjANWhuVBEn4clCwlug==", - "dev": true + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.2.tgz", + "integrity": "sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/node": { - "version": "20.2.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.3.tgz", - "integrity": "sha512-pg9d0yC4rVNWQzX8U7xb4olIOFuuVL9za3bzMT2pu2SU0SNEi66i2qrvhE2qt0HvkhuCaWJu7pLNOt/Pj8BIrw==" + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.2.tgz", + "integrity": "sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] }, - "node_modules/@types/prop-types": { - "version": "15.7.5", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", - "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.2.tgz", + "integrity": "sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] }, - "node_modules/@types/react": { - "version": "18.2.6", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.6.tgz", - "integrity": "sha512-wRZClXn//zxCFW+ye/D2qY65UsYP1Fpex2YXorHc8awoNamkMZSvBxwxdYVInsHOZZd2Ppq8isnSzJL5Mpf8OA==", - "dependencies": { - "@types/prop-types": "*", - "@types/scheduler": "*", - "csstype": "^3.0.2" - } + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.2.tgz", + "integrity": "sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/@types/react-dom": { - "version": "18.2.4", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.4.tgz", - "integrity": "sha512-G2mHoTMTL4yoydITgOGwWdWMVd8sNgyEP85xVmMKAPUBwQWm9wBPQUmvbeF4V3WBY1P7mmL4BkjQ0SqUpf1snw==", - "dependencies": { - "@types/react": "*" - } + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.2.tgz", + "integrity": "sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/@types/scheduler": { - "version": "0.16.3", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", - "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==" + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.2.tgz", + "integrity": "sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", - "dev": true + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.2.tgz", + "integrity": "sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" + "node_modules/@rushstack/eslint-patch": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.12.0.tgz", + "integrity": "sha512-5EwMtOqvJMMa3HbmxLlF74e+3/HhwBTMcvt3nqVJgGCozO6hzIPOBlwm8mGVNR9SN2IJpxSnlxczyDjcn7qIyw==", + "dev": true, + "license": "MIT" }, - "node_modules/@types/testing-library__jest-dom": { - "version": "5.14.5", - "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.5.tgz", - "integrity": "sha512-SBwbxYoyPIvxHbeHxTZX2Pe/74F/tX2/D3mMvzabdeJ25bBojfW0TyB8BHrbq/9zaaKICJZjLP+8r6AeZMFCuQ==", + "node_modules/@rushstack/eslint-plugin": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-plugin/-/eslint-plugin-0.19.0.tgz", + "integrity": "sha512-WM1q+JbfFLY+/G1Jf+RgpDkU3R06zv5pm2JnDLcLUgc3kuCxurqxqtUpzp9yZn9G4zf0NbjKP2teZuDR7B3X2A==", + "dev": true, + "license": "MIT", "dependencies": { - "@types/jest": "*" + "@rushstack/tree-pattern": "0.3.4", + "@typescript-eslint/utils": "~8.31.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" } }, - "node_modules/@types/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA==", - "dev": true - }, - "node_modules/@types/ws": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-6.0.4.tgz", - "integrity": "sha512-PpPrX7SZW9re6+Ha8ojZG4Se8AZXgf0GK6zmfqEuCsY49LFDNXO3SByp44X3dFEqtB73lkCDAdUazhAjVPiNwg==", + "node_modules/@rushstack/eslint-plugin-security": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-plugin-security/-/eslint-plugin-security-0.11.0.tgz", + "integrity": "sha512-c7UojOyNQDD7fwtj7NJx4x8ZU0KeKnefVDEe+f16ZQT6sIXy8CCmbEwduCgGZugIPqwV9hXYHNJiWZtU3iDXng==", "dev": true, + "license": "MIT", "dependencies": { - "@types/node": "*" + "@rushstack/tree-pattern": "0.3.4", + "@typescript-eslint/utils": "~8.31.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" } }, - "node_modules/@types/yargs": { - "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", - "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", + "node_modules/@rushstack/eslint-plugin-security/node_modules/@typescript-eslint/scope-manager": { + "version": "8.31.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.31.1.tgz", + "integrity": "sha512-BMNLOElPxrtNQMIsFHE+3P0Yf1z0dJqV9zLdDxN/xLlWMlXK/ApEsVEKzpizg9oal8bAT5Sc7+ocal7AC1HCVw==", + "dev": true, + "license": "MIT", "dependencies": { - "@types/yargs-parser": "*" + "@typescript-eslint/types": "8.31.1", + "@typescript-eslint/visitor-keys": "8.31.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" - }, - "node_modules/@types/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", + "node_modules/@rushstack/eslint-plugin-security/node_modules/@typescript-eslint/types": { + "version": "8.31.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.31.1.tgz", + "integrity": "sha512-SfepaEFUDQYRoA70DD9GtytljBePSj17qPxFHA/h3eg6lPTqGJ5mWOtbXCk1YrVU1cTJRd14nhaXWFu0l2troQ==", "dev": true, - "optional": true, - "dependencies": { - "@types/node": "*" + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.59.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.6.tgz", - "integrity": "sha512-sXtOgJNEuRU5RLwPUb1jxtToZbgvq3M6FPpY4QENxoOggK+UpTxUBpj6tD8+Qh2g46Pi9We87E+eHnUw8YcGsw==", + "node_modules/@rushstack/eslint-plugin-security/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.31.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.31.1.tgz", + "integrity": "sha512-kaA0ueLe2v7KunYOyWYtlf/QhhZb7+qh4Yw6Ni5kgukMIG+iP773tjgBiLWIXYumWCwEq3nLW+TUywEp8uEeag==", "dev": true, + "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.59.6", - "@typescript-eslint/type-utils": "5.59.6", - "@typescript-eslint/utils": "5.59.6", + "@typescript-eslint/types": "8.31.1", + "@typescript-eslint/visitor-keys": "8.31.1", "debug": "^4.3.4", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/@typescript-eslint/parser": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.7.tgz", - "integrity": "sha512-VhpsIEuq/8i5SF+mPg9jSdIwgMBBp0z9XqjiEay+81PYLJuroN+ET1hM5IhkiYMJd9MkTz8iJLt7aaGAgzWUbQ==", + "node_modules/@rushstack/eslint-plugin-security/node_modules/@typescript-eslint/utils": { + "version": "8.31.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.31.1.tgz", + "integrity": "sha512-2DSI4SNfF5T4oRveQ4nUrSjUqjMND0nLq9rEkz0gfGr3tg0S5KB6DhwR+WZPCjzkZl3cH+4x2ce3EsL50FubjQ==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "5.59.7", - "@typescript-eslint/types": "5.59.7", - "@typescript-eslint/typescript-estree": "5.59.7", - "debug": "^4.3.4" + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.31.1", + "@typescript-eslint/types": "8.31.1", + "@typescript-eslint/typescript-estree": "8.31.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.7.tgz", - "integrity": "sha512-FL6hkYWK9zBGdxT2wWEd2W8ocXMu3K94i3gvMrjXpx+koFYdYV7KprKfirpgY34vTGzEPPuKoERpP8kD5h7vZQ==", + "node_modules/@rushstack/eslint-plugin-security/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.31.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.31.1.tgz", + "integrity": "sha512-I+/rgqOVBn6f0o7NDTmAPWWC6NuqhV174lfYvAm9fUaWeiefLdux9/YI3/nLugEn9L8fcSi0XmpKi/r5u0nmpw==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "5.59.7", - "@typescript-eslint/visitor-keys": "5.59.7" + "@typescript-eslint/types": "8.31.1", + "eslint-visitor-keys": "^4.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.7.tgz", - "integrity": "sha512-UnVS2MRRg6p7xOSATscWkKjlf/NDKuqo5TdbWck6rIRZbmKpVNTLALzNvcjIfHBE7736kZOFc/4Z3VcZwuOM/A==", + "node_modules/@rushstack/eslint-plugin-security/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, + "license": "Apache-2.0", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://opencollective.com/eslint" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.7.tgz", - "integrity": "sha512-4A1NtZ1I3wMN2UGDkU9HMBL+TIQfbrh4uS0WDMMpf3xMRursDbqEf1ahh6vAAe3mObt8k3ZATnezwG4pdtWuUQ==", + "node_modules/@rushstack/eslint-plugin-security/node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.59.7", - "@typescript-eslint/visitor-keys": "5.59.7", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, + "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=18.12" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "typescript": ">=4.8.4" } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.7.tgz", - "integrity": "sha512-tyN+X2jvMslUszIiYbF0ZleP+RqQsFVpGrKI6e0Eet1w8WmhsAtmzaqm8oM8WJQ1ysLwhnsK/4hYHJjOgJVfQQ==", + "node_modules/@rushstack/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { + "version": "8.31.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.31.1.tgz", + "integrity": "sha512-BMNLOElPxrtNQMIsFHE+3P0Yf1z0dJqV9zLdDxN/xLlWMlXK/ApEsVEKzpizg9oal8bAT5Sc7+ocal7AC1HCVw==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "5.59.7", - "eslint-visitor-keys": "^3.3.0" + "@typescript-eslint/types": "8.31.1", + "@typescript-eslint/visitor-keys": "8.31.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.59.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.6.tgz", - "integrity": "sha512-gLbY3Le9Dxcb8KdpF0+SJr6EQ+hFGYFl6tVY8VxLPFDfUZC7BHFw+Vq7bM5lE9DwWPfx4vMWWTLGXgpc0mAYyQ==", + "node_modules/@rushstack/eslint-plugin/node_modules/@typescript-eslint/types": { + "version": "8.31.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.31.1.tgz", + "integrity": "sha512-SfepaEFUDQYRoA70DD9GtytljBePSj17qPxFHA/h3eg6lPTqGJ5mWOtbXCk1YrVU1cTJRd14nhaXWFu0l2troQ==", "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.59.6", - "@typescript-eslint/visitor-keys": "5.59.6" - }, + "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/type-utils": { - "version": "5.59.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.6.tgz", - "integrity": "sha512-A4tms2Mp5yNvLDlySF+kAThV9VTBPCvGf0Rp8nl/eoDX9Okun8byTKoj3fJ52IJitjWOk0fKPNQhXEB++eNozQ==", + "node_modules/@rushstack/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.31.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.31.1.tgz", + "integrity": "sha512-kaA0ueLe2v7KunYOyWYtlf/QhhZb7+qh4Yw6Ni5kgukMIG+iP773tjgBiLWIXYumWCwEq3nLW+TUywEp8uEeag==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "5.59.6", - "@typescript-eslint/utils": "5.59.6", + "@typescript-eslint/types": "8.31.1", + "@typescript-eslint/visitor-keys": "8.31.1", "debug": "^4.3.4", - "tsutils": "^3.21.0" + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "5.59.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.6.tgz", - "integrity": "sha512-tH5lBXZI7T2MOUgOWFdVNUILsI02shyQvfzG9EJkoONWugCG77NDDa1EeDGw7oJ5IvsTAAGVV8I3Tk2PNu9QfA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.59.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.6.tgz", - "integrity": "sha512-vW6JP3lMAs/Tq4KjdI/RiHaaJSO7IUsbkz17it/Rl9Q+WkQ77EOuOnlbaU8kKfVIOJxMhnRiBG+olE7f3M16DA==", + "node_modules/@rushstack/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "8.31.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.31.1.tgz", + "integrity": "sha512-2DSI4SNfF5T4oRveQ4nUrSjUqjMND0nLq9rEkz0gfGr3tg0S5KB6DhwR+WZPCjzkZl3cH+4x2ce3EsL50FubjQ==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "5.59.6", - "@typescript-eslint/visitor-keys": "5.59.6", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.31.1", + "@typescript-eslint/types": "8.31.1", + "@typescript-eslint/typescript-estree": "8.31.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/@typescript-eslint/utils": { - "version": "5.59.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.6.tgz", - "integrity": "sha512-vzaaD6EXbTS29cVH0JjXBdzMt6VBlv+hE31XktDRMX1j3462wZCJa7VzO2AxXEXcIl8GQqZPcOPuW/Z1tZVogg==", + "node_modules/@rushstack/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.31.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.31.1.tgz", + "integrity": "sha512-I+/rgqOVBn6f0o7NDTmAPWWC6NuqhV174lfYvAm9fUaWeiefLdux9/YI3/nLugEn9L8fcSi0XmpKi/r5u0nmpw==", "dev": true, + "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.6", - "@typescript-eslint/types": "5.59.6", - "@typescript-eslint/typescript-estree": "5.59.6", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" + "@typescript-eslint/types": "8.31.1", + "eslint-visitor-keys": "^4.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.59.6", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.6.tgz", - "integrity": "sha512-zEfbFLzB9ETcEJ4HZEEsCR9HHeNku5/Qw1jSS5McYJv5BR+ftYXwFFAH5Al+xkGaZEqowMwl7uoJjQb1YSPF8Q==", + "node_modules/@rushstack/eslint-plugin/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.59.6", - "eslint-visitor-keys": "^3.3.0" - }, + "license": "Apache-2.0", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://opencollective.com/eslint" } }, - "node_modules/@vitejs/plugin-react": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-3.1.0.tgz", - "integrity": "sha512-AfgcRL8ZBhAlc3BFdigClmTUMISmmzHn7sB2h9U1odvc5U/MjWXsAaz18b/WoppUTDBzxOJwo2VdClfUcItu9g==", + "node_modules/@rushstack/eslint-plugin/node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", "dev": true, - "dependencies": { - "@babel/core": "^7.20.12", - "@babel/plugin-transform-react-jsx-self": "^7.18.6", - "@babel/plugin-transform-react-jsx-source": "^7.19.6", - "magic-string": "^0.27.0", - "react-refresh": "^0.14.0" - }, + "license": "MIT", "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": ">=18.12" }, "peerDependencies": { - "vite": "^4.1.0-beta.0" + "typescript": ">=4.8.4" } }, - "node_modules/@webassemblyjs/ast": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", - "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", - "dev": true, - "peer": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "node_modules/@rushstack/tree-pattern": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@rushstack/tree-pattern/-/tree-pattern-0.3.4.tgz", + "integrity": "sha512-9uROnkiHWsQqxW6HirXABfTRlgzhYp6tevbYIGkwKQ09VaayUBkvFvt/urDKMwlo+tGU0iQQLuVige6c48wTgw==", "dev": true, - "peer": true + "license": "MIT" }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true, - "peer": true + "node_modules/@sinclair/typebox": { + "version": "0.34.49", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.49.tgz", + "integrity": "sha512-brySQQs7Jtn0joV8Xh9ZV/hZb9Ozb0pmazDIASBkYKCjXrXU3mpcFahmK/z4YDhGkQvP9mWJbVyahdtU5wQA+A==", + "license": "MIT" }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", - "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", "dev": true, - "peer": true + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", "dev": true, - "peer": true, + "license": "BSD-3-Clause", "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@xtuc/long": "4.2.2" + "@sinonjs/commons": "^3.0.0" } }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true, - "peer": true + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "license": "MIT" }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", - "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", "dev": true, - "peer": true, + "license": "MIT" + }, + "node_modules/@swc/helpers": { + "version": "0.5.23", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz", + "integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==", + "license": "Apache-2.0", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6" + "tslib": "^2.8.0" } }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", - "dev": true, + "node_modules/@testing-library/dom": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", + "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", + "license": "MIT", "peer": true, "dependencies": { - "@xtuc/ieee754": "^1.2.0" + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "picocolors": "1.1.1", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" } }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", - "dev": true, - "peer": true, + "node_modules/@testing-library/jest-dom": { + "version": "5.17.0", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz", + "integrity": "sha512-ynmNeT7asXyH3aSVv4vvX4Rb+0qjOhdNHnO/3vuZNqPmhDpV/+rCSGwQ7bLcmU2cJ4dvoheIO85LQj0IbJHEtg==", + "license": "MIT", "dependencies": { - "@xtuc/long": "4.2.2" + "@adobe/css-tools": "^4.0.1", + "@babel/runtime": "^7.9.2", + "@types/testing-library__jest-dom": "^5.9.1", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.5.6", + "lodash": "^4.17.15", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=8", + "npm": ">=6", + "yarn": ">=1" } }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true, - "peer": true - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", - "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", - "dev": true, - "peer": true, + "node_modules/@testing-library/jest-dom/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-opt": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6", - "@webassemblyjs/wast-printer": "1.11.6" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", - "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", - "dev": true, - "peer": true, + "node_modules/@testing-library/react": { + "version": "13.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-13.4.0.tgz", + "integrity": "sha512-sXOGON+WNTh3MLE9rve97ftaZukN3oNf2KjDy7YTx6hcTO2uuLHuCGynMDhFwGw/jYf4OJ2Qk0i4i79qMNNkyw==", + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^8.5.0", + "@types/react-dom": "^18.0.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", - "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", - "dev": true, - "peer": true, + "node_modules/@testing-library/react/node_modules/@testing-library/dom": { + "version": "8.20.1", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.20.1.tgz", + "integrity": "sha512-/DiOQ5xBxgdYRC8LNk7U+RWat0S3qRLeIw3ZIkMQ9kkVlRmwD/Eg8k8CqIpD6GW7u20JIUOfMKbxtiLutpjQ4g==", + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6" + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.1.3", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=12" } }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", - "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", - "dev": true, - "peer": true, + "node_modules/@testing-library/react/node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "license": "Apache-2.0", "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "deep-equal": "^2.0.5" } }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", - "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", - "dev": true, - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@xtuc/long": "4.2.2" + "node_modules/@testing-library/user-event": { + "version": "14.6.1", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.6.1.tgz", + "integrity": "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==", + "license": "MIT", + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" } }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true, - "peer": true + "node_modules/@tiny-calc/nano": { + "version": "0.0.0-alpha.5", + "resolved": "https://registry.npmjs.org/@tiny-calc/nano/-/nano-0.0.0-alpha.5.tgz", + "integrity": "sha512-Hs37tz9ZtvK21/5s4tjt5RBa/PFHKYS0AzvdxiXuSd3+AKQN2ygxw7uwD9j0DIG9qONddg1vIASO77JIGyZzyw==", + "license": "MIT" }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", "dev": true, - "peer": true - }, - "node_modules/abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "dev": true + "license": "MIT" }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "node_modules/@ts-morph/common": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.23.0.tgz", + "integrity": "sha512-m7Lllj9n/S6sOkCkRftpM7L24uvmfXQFedlW/4hENcuJH1HHm9u5EgxZb9uVjQSCGrbBWBkOGgcTxNg36r6ywA==", + "dev": true, + "license": "MIT", "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" + "fast-glob": "^3.3.2", + "minimatch": "^9.0.3", + "mkdirp": "^3.0.1", + "path-browserify": "^1.0.1" } }, - "node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "node_modules/@ts-morph/common/node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", "dev": true, + "license": "MIT", "bin": { - "acorn": "bin/acorn" + "mkdirp": "dist/cjs/src/bin.js" }, "engines": { - "node": ">=0.4.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/acorn-globals": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", - "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", + "node_modules/@tybys/wasm-util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", + "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", "dev": true, + "license": "MIT", + "optional": true, "dependencies": { - "acorn": "^8.1.0", - "acorn-walk": "^8.0.2" + "tslib": "^2.4.0" } }, - "node_modules/acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "dev": true, - "peer": true, - "peerDependencies": { - "acorn": "^8" - } + "node_modules/@tylerbu/sorted-btree-es6": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@tylerbu/sorted-btree-es6/-/sorted-btree-es6-2.1.1.tgz", + "integrity": "sha512-M0EHlEW9Aaz0P8NT/pC1E6wAfuWY7TpvF4U1Ha3wE87KEhiiahnFbHbzmwGsLxm7ma70A/L94cu5pqvickF2nw==", + "license": "MIT" }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "license": "MIT" + }, + "node_modules/@types/assert": { + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/@types/assert/-/assert-1.5.11.tgz", + "integrity": "sha512-FjS1mxq2dlGr9N4z72/DO+XmyRS3ZZIoVn998MEopAN/OmyN28F4yumRL5pOw2z+hbFLuWGYuF2rrw5p11xM5A==", "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } + "license": "MIT" }, - "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, - "engines": { - "node": ">=0.4.0" + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" } }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", "dev": true, + "license": "MIT", "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" + "@babel/types": "^7.0.0" } }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dev": true, + "license": "MIT", "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", "dev": true, + "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "@babel/types": "^7.28.2" } }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "node_modules/@types/babylonjs": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/babylonjs/-/babylonjs-2.4.1.tgz", + "integrity": "sha512-vt6db2PxisxsnLvL5holHLV9vMJzELAhFq54syX/tKncTmjeraQSR1W20j9/KYLEpAFU18u76rK8utb8JlUrtQ==", + "deprecated": "This is a stub types definition for BabylonJS (http://www.babylonjs.com/). BabylonJS provides its own type definitions, so you don't need @types/babylonjs installed!", "dev": true, + "license": "MIT", "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } + "babylonjs": "*" } }, - "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, + "node_modules/@types/debug": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", + "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", + "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "@types/ms": "*" } }, - "node_modules/ajv-formats/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "node_modules/@types/double-ended-queue": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@types/double-ended-queue/-/double-ended-queue-2.1.7.tgz", + "integrity": "sha512-OVbdb2iOJakEg/Ou6dVZsH0LLxlO+GFjc1FB2W8/jT7bnhoFVJwnZOqi/H26ospeMBaEbGiX3Qy2a7r6pfZKXQ==", + "license": "MIT" }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", "dev": true, - "peer": true, + "license": "MIT" + }, + "node_modules/@types/events": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.3.tgz", + "integrity": "sha512-trOc4AAUThEz9hapPtSd7wf5tiQKvTtu5b371UxXdTuqzIh0ArcRspRP0i0Viu+LXstIQ1z96t1nsPxT9ol01g==", + "license": "MIT" + }, + "node_modules/@types/events_pkg": { + "name": "@types/events", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.3.tgz", + "integrity": "sha512-trOc4AAUThEz9hapPtSd7wf5tiQKvTtu5b371UxXdTuqzIh0ArcRspRP0i0Viu+LXstIQ1z96t1nsPxT9ol01g==", + "license": "MIT" + }, + "node_modules/@types/ioredis-mock": { + "version": "8.2.7", + "resolved": "https://registry.npmjs.org/@types/ioredis-mock/-/ioredis-mock-8.2.7.tgz", + "integrity": "sha512-YsGiaOIYBKeVvu/7GYziAD8qX3LJem5LK00d5PKykzsQJMLysAqXA61AkNuYWCekYl64tbMTqVOMF4SYoCPbQg==", + "license": "MIT", "peerDependencies": { - "ajv": "^6.9.1" + "ioredis": ">=5" } }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "license": "MIT" }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" } }, - "node_modules/ansi-sequence-parser": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.0.tgz", - "integrity": "sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ==", - "dev": true + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@types/jest": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-30.0.0.tgz", + "integrity": "sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==", + "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" - }, + "expect": "^30.0.0", + "pretty-format": "^30.0.0" + } + }, + "node_modules/@types/jest/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, + "node_modules/@types/jest/node_modules/pretty-format": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.4.1.tgz", + "integrity": "sha512-K6KiKMHTL4jjX4u3Kir2EW07nRfcqVTXIImx50wbjHQTcZPgg+gjVeNTIT3l3L1Rd4UefxfogquC9J37SoFyyw==", + "license": "MIT", "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "@jest/schemas": "30.4.1", + "ansi-styles": "^5.2.0", + "react-is-18": "npm:react-is@^18.3.1", + "react-is-19": "npm:react-is@^19.2.5" }, "engines": { - "node": ">= 8" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/append-transform": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", - "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true, - "dependencies": { - "default-require-extensions": "^3.0.0" - }, - "engines": { - "node": ">=8" - } + "license": "MIT" }, - "node_modules/archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", - "dev": true + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true, + "license": "MIT", + "optional": true }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true + "node_modules/@types/lodash": { + "version": "4.17.24", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.24.tgz", + "integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==", + "license": "MIT" }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "node_modules/@types/mocha": { + "version": "10.0.10", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.10.tgz", + "integrity": "sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==", + "dev": true, + "license": "MIT" }, - "node_modules/aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", - "dependencies": { - "deep-equal": "^2.0.5" - } + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" }, - "node_modules/arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "node_modules/@types/nconf": { + "version": "0.10.7", + "resolved": "https://registry.npmjs.org/@types/nconf/-/nconf-0.10.7.tgz", + "integrity": "sha512-ltJgbQX0XgjkeDrz0anTCXLBLatppWYFCxp88ILEwybfAuyNWr0Qb+ceFFqZ0VDR8fguEjr0hH37ZF+AF4gsxw==", + "license": "MIT" }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "node_modules/@types/node": { + "version": "26.0.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.0.1.tgz", + "integrity": "sha512-fc3KiUoBt6kie0N9bIW3E47vZsuaMf0PM2AaUpLCLT0s/LvX1nxAim6Fc049cNxODPpGm6qRAuUOB86SkRuPQw==", + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "undici-types": "~8.3.0" } }, - "node_modules/array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", "dev": true, + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.28", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz", + "integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==", + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@types/prop-types": "*", + "csstype": "^3.2.2" } }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" + "node_modules/@types/react-dom": { + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "^18.0.0" } }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "node_modules/@types/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==", + "license": "MIT" }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz", - "integrity": "sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==", - "dev": true, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "license": "MIT" + }, + "node_modules/@types/testing-library__jest-dom": { + "version": "5.14.9", + "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.9.tgz", + "integrity": "sha512-FSYhIjFlfOpGSRyVoMBMuS3ws5ehFQODymf3vlI7U1K8c7PHwWwFY7VREfmsuzHSOnoKs/9/Y983ayOs7eRzqw==", + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.1.3" + "@types/jest": "*" } }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "node_modules/@types/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA==", "dev": true, - "engines": { - "node": ">=0.10.0" + "license": "MIT" + }, + "node_modules/@types/ws": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-6.0.4.tgz", + "integrity": "sha512-PpPrX7SZW9re6+Ha8ojZG4Se8AZXgf0GK6zmfqEuCsY49LFDNXO3SByp44X3dFEqtB73lkCDAdUazhAjVPiNwg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" } }, - "node_modules/async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", - "dev": true + "node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } }, - "node_modules/async-mutex": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.3.2.tgz", - "integrity": "sha512-HuTK7E7MT7jZEh1P9GtRW9+aTWiDWWi9InbZ5hjxrnRa39KS4BW04+xLBhYNS2aXhHUIKZSw3gj4Pn1pj+qGAA==", + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "license": "MIT" + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", "dev": true, + "license": "MIT", + "optional": true, "dependencies": { - "tslib": "^2.3.1" + "@types/node": "*" } }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", + "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/type-utils": "7.18.0", + "@typescript-eslint/utils": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, "engines": { - "node": ">= 0.4" + "node": "^18.18.0 || >=20.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "node_modules/@typescript-eslint/parser": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", + "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "follow-redirects": "^1.14.8" + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/babel-loader": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.1.2.tgz", - "integrity": "sha512-mN14niXW43tddohGl8HPu5yfQq70iUThvFL/4QzESA7GcZoC0eVOhvWdQ8+3UlSjaDE9MVtsW9mxDY07W7VpVA==", + "node_modules/@typescript-eslint/project-service": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.4.tgz", + "integrity": "sha512-nPiRSKuvtTN+no/2N1kt2tUh/HoFzeEgOm9fQ6XQk4/ApGqjx0zFIIaLJ6wooR1HIoozvj2j6vTi/1fgAz7UYQ==", "dev": true, + "license": "MIT", "dependencies": { - "find-cache-dir": "^3.3.2", - "schema-utils": "^4.0.0" + "@typescript-eslint/tsconfig-utils": "^8.46.4", + "@typescript-eslint/types": "^8.46.4", + "debug": "^4.3.4" }, "engines": { - "node": ">= 14.15.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@babel/core": "^7.12.0", - "webpack": ">=5" + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/babylonjs": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/babylonjs/-/babylonjs-6.21.0.tgz", - "integrity": "sha512-WU+s8i9PjV6j77iI/VLn1Vakkl0y0gBIwJE6Ks+iq36yuo9NJAvrYDnC0OqeQWs9gnsSJ26xgKpftrpJ01t1Sg==", + "node_modules/@typescript-eslint/project-service/node_modules/@typescript-eslint/types": { + "version": "8.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.62.0.tgz", + "integrity": "sha512-KvAclkktORPvM54TgLgA4z9HIV1M8zOgw9ZVNXl9f/8dLYfXYX1wkMXP7qmabpijQRV5bHJLOmoyGQbLMaUYeg==", "dev": true, - "hasInstallScript": true - }, - "node_modules/babylonjs-gltf2interface": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/babylonjs-gltf2interface/-/babylonjs-gltf2interface-6.21.0.tgz", - "integrity": "sha512-KSQ5WrtSV3GUB8KkBTEe5xVxgY2JmvUH+J58OyK+iLnzeExleaCWlRNw2ZNxxozYc4sA+dZ8TBnPhPdfyvRS2Q==", - "peer": true - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", + "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0" + }, "engines": { - "node": ">=8" + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.46.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.4.tgz", + "integrity": "sha512-+/XqaZPIAk6Cjg7NWgSGe27X4zMGqrFqZ8atJsX3CWxH/jACqWnrWI68h7nHQld0y+k9eTTjb9r+KU4twLoo9A==", "dev": true, - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/bl/node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "node_modules/@typescript-eslint/type-utils": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz", + "integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "license": "MIT", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/utils": "7.18.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true + "node_modules/@typescript-eslint/types": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", + "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", + "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "node_modules/@typescript-eslint/utils": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", + "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", + "dev": true, + "license": "MIT", "dependencies": { - "fill-range": "^7.0.1" + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0" }, "engines": { - "node": ">=8" + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" } }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", + "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], + "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" + "@typescript-eslint/types": "7.18.0", + "eslint-visitor-keys": "^3.4.3" }, - "bin": { - "browserslist": "cli.js" + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typespec/ts-http-runtime": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@typespec/ts-http-runtime/-/ts-http-runtime-0.3.6.tgz", + "integrity": "sha512-jIXhD0eWQ1JA6ln/5Dltyx22UxWNrw0hZmhy2rlv6m6KgF7kplHx3g0fzi09lNmTJQRR91OlemYp3xFnvDK9og==", + "dev": true, + "license": "MIT", + "dependencies": { + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "node": ">=20.0.0" } }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "node_modules/@typespec/ts-http-runtime/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", "dev": true, + "license": "MIT", "engines": { - "node": "*" + "node": ">= 14" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/caching-transform": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", - "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", + "node_modules/@typespec/ts-http-runtime/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "dev": true, + "license": "MIT", "dependencies": { - "hasha": "^5.0.0", - "make-dir": "^3.0.0", - "package-hash": "^4.0.0", - "write-file-atomic": "^3.0.0" + "agent-base": "^7.1.2", + "debug": "4" }, "engines": { - "node": ">=8" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 14" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "node_modules/@ungap/structured-clone": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.2.tgz", + "integrity": "sha512-5jsZFwgR5rTdKwidH9Qmat75RKwqfpKlWWB1frDkljN127mwqBu8K0PYo7/hFpF03IEJpfVPpCQDY/eDx3iHvA==", "dev": true, - "engines": { - "node": ">=6" - } + "license": "ISC" }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.12.2.tgz", + "integrity": "sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==", + "cpu": [ + "arm" + ], "dev": true, - "engines": { - "node": ">=6" - } + "license": "MIT", + "optional": true, + "os": [ + "android" + ] }, - "node_modules/caniuse-lite": { - "version": "1.0.30001488", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001488.tgz", - "integrity": "sha512-NORIQuuL4xGpIy6iCCQGN4iFjlBXtfKWIenlUuyZJumLRIindLb7wXM+GO8erEhb7vXfcnf4BAg2PrSDN5TNLQ==", + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.12.2.tgz", + "integrity": "sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==", + "cpu": [ + "arm64" + ], "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } + "license": "MIT", + "optional": true, + "os": [ + "android" ] }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/check-more-types": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", - "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.12.2.tgz", + "integrity": "sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==", + "cpu": [ + "arm64" + ], "dev": true, - "engines": { - "node": ">= 0.8.0" - } + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.12.2.tgz", + "integrity": "sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==", + "cpu": [ + "x64" ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.12.2.tgz", + "integrity": "sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==", + "cpu": [ + "x64" + ], "dev": true, - "peer": true, - "engines": { - "node": ">=6.0" - } + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] }, - "node_modules/chromium-bidi": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.9.tgz", - "integrity": "sha512-u3DC6XwgLCA9QJ5ak1voPslCmacQdulZNCPsI3qNXxSnEcZS7DFIbww+5RM2bznMEje7cc0oydavRLRvOIZtHw==", + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.12.2.tgz", + "integrity": "sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "mitt": "3.0.0" - }, - "peerDependencies": { - "devtools-protocol": "*" - } + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.12.2.tgz", + "integrity": "sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==", + "cpu": [ + "arm" ], - "engines": { - "node": ">=8" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true, - "engines": { - "node": ">=6" - } + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.12.2.tgz", + "integrity": "sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/clone-deep": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz", - "integrity": "sha512-we+NuQo2DHhSl+DP6jlUiAhyAjBQrYnpOk15rN6c6JSPScjiCLh8IbSU+VTcph6YS3o7mASE8a0+gbZ7ChLpgg==", + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.12.2.tgz", + "integrity": "sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "for-own": "^0.1.3", - "is-plain-object": "^2.0.1", - "kind-of": "^3.0.2", - "lazy-cache": "^1.0.3", - "shallow-clone": "^0.1.2" - }, - "engines": { - "node": ">=0.10.0" - } + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } + "node_modules/@unrs/resolver-binding-linux-loong64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-gnu/-/resolver-binding-linux-loong64-gnu-1.12.2.tgz", + "integrity": "sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "node_modules/@unrs/resolver-binding-linux-loong64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-musl/-/resolver-binding-linux-loong64-musl-1.12.2.tgz", + "integrity": "sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.12.2.tgz", + "integrity": "sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==", + "cpu": [ + "ppc64" + ], "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.12.2.tgz", + "integrity": "sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==", + "cpu": [ + "riscv64" + ], "dev": true, - "engines": { - "node": ">= 6" - } + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.12.2.tgz", + "integrity": "sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.12.2.tgz", + "integrity": "sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/concurrently": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-5.3.0.tgz", - "integrity": "sha512-8MhqOB6PWlBfA2vJ8a0bSFKATOdWlHiQlk11IfmQBPaHVP8oP2gsh2MObE6UR3hqDHqvaIvLTyceNW6obVuFHQ==", + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.12.2.tgz", + "integrity": "sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.12.2.tgz", + "integrity": "sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-openharmony-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-openharmony-arm64/-/resolver-binding-openharmony-arm64-1.12.2.tgz", + "integrity": "sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==", + "cpu": [ + "arm64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.12.2.tgz", + "integrity": "sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, "dependencies": { - "chalk": "^2.4.2", - "date-fns": "^2.0.1", - "lodash": "^4.17.15", - "read-pkg": "^4.0.1", - "rxjs": "^6.5.2", - "spawn-command": "^0.0.2-1", - "supports-color": "^6.1.0", - "tree-kill": "^1.2.2", - "yargs": "^13.3.0" - }, - "bin": { - "concurrently": "bin/concurrently.js" + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" }, "engines": { - "node": ">=6.0.0" + "node": ">=14.0.0" } }, - "node_modules/concurrently/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.12.2.tgz", + "integrity": "sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==", + "cpu": [ + "arm64" + ], "dev": true, - "engines": { - "node": ">=6" - } + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/concurrently/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.12.2.tgz", + "integrity": "sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==", + "cpu": [ + "ia32" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.12.2.tgz", + "integrity": "sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@videojs/http-streaming": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-3.17.4.tgz", + "integrity": "sha512-XAvdG2dolBuV2Fx8bu1kjmQ2D4TonGzZH68Pgv/O9xMSFWdZtITSMFismeQLEAtMmGwze8qNJp3RgV+jStrJqg==", + "license": "Apache-2.0", "dependencies": { - "color-convert": "^1.9.0" + "@babel/runtime": "^7.12.5", + "@videojs/vhs-utils": "^4.1.1", + "aes-decrypter": "^4.0.2", + "global": "^4.4.0", + "m3u8-parser": "^7.2.0", + "mpd-parser": "^1.3.1", + "mux.js": "7.1.0", + "video.js": "^7 || ^8" }, "engines": { - "node": ">=4" + "node": ">=8", + "npm": ">=5" + }, + "peerDependencies": { + "video.js": "^8.19.0" } }, - "node_modules/concurrently/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, + "node_modules/@videojs/vhs-utils": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-4.1.2.tgz", + "integrity": "sha512-1Dsv5dtWOq0LP1G37O46FQFA2tKAZON5UMe6dFPxT7JvPhEx8QIXcFQxan8+hHI3fX6aomFRFrUBJNgRYQDSXA==", + "license": "MIT", "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "@babel/runtime": "^7.12.5", + "global": "^4.4.0" }, "engines": { - "node": ">=4" + "node": ">=8", + "npm": ">=5" } }, - "node_modules/concurrently/node_modules/chalk/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, + "node_modules/@videojs/xhr": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@videojs/xhr/-/xhr-2.7.0.tgz", + "integrity": "sha512-giab+EVRanChIupZK7gXjHy90y3nncA2phIOyG3Ne5fvpiMJzvqYwiTOnEVW2S4CoYcuKJkomat7bMXA/UoUZQ==", + "license": "MIT", "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" + "@babel/runtime": "^7.5.5", + "global": "~4.4.0", + "is-function": "^1.0.1" } }, - "node_modules/concurrently/node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "node_modules/@vitejs/plugin-react": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.2.0.tgz", + "integrity": "sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==", "dev": true, + "license": "MIT", "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" + "@babel/core": "^7.29.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-rc.3", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.18.0" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/concurrently/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/@webassemblyjs/ast": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "color-name": "1.1.3" + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, - "node_modules/concurrently/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "dev": true, + "license": "MIT", + "peer": true }, - "node_modules/concurrently/node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "dev": true, + "license": "MIT", + "peer": true }, - "node_modules/concurrently/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", "dev": true, - "engines": { - "node": ">=0.8.0" - } + "license": "MIT", + "peer": true }, - "node_modules/concurrently/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" } }, - "node_modules/concurrently/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", "dev": true, - "engines": { - "node": ">=4" - } + "license": "MIT", + "peer": true }, - "node_modules/concurrently/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", "dev": true, - "engines": { - "node": ">=4" + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" } }, - "node_modules/concurrently/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "node_modules/@webassemblyjs/ieee754": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" + "@xtuc/ieee754": "^1.2.0" } }, - "node_modules/concurrently/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/@webassemblyjs/leb128": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", "dev": true, + "license": "Apache-2.0", + "peer": true, "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "@xtuc/long": "4.2.2" } }, - "node_modules/concurrently/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "node_modules/@webassemblyjs/utf8": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } + "license": "MIT", + "peer": true }, - "node_modules/concurrently/node_modules/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - }, - "engines": { - "node": ">=4" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" } }, - "node_modules/concurrently/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", "dev": true, - "engines": { - "node": ">=4" + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, - "node_modules/concurrently/node_modules/read-pkg": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-4.0.1.tgz", - "integrity": "sha512-+UBirHHDm5J+3WDmLBZYSklRYg82nMlz+enn+GMZ22nSR2f4bzxmhso6rzQW/3mT2PVzpzDTiYIZahk8UmZ44w==", + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "normalize-package-data": "^2.3.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0" - }, - "engines": { - "node": ">=6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" } }, - "node_modules/concurrently/node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, - "node_modules/concurrently/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" + "@webassemblyjs/ast": "1.14.1", + "@xtuc/long": "4.2.2" } }, - "node_modules/concurrently/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.13", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.13.tgz", + "integrity": "sha512-KRYzxepc14G/CEpEGc3Yn+JKaAeT63smlDr+vjB8jRfgTBBI9wRj/nkQEO+ucV8p8I9bfKLWp37uHgFrbntPvw==", + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=10.0.0" } }, - "node_modules/concurrently/node_modules/supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=6" - } + "license": "BSD-3-Clause", + "peer": true }, - "node_modules/concurrently/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true, + "license": "Apache-2.0", + "peer": true }, - "node_modules/concurrently/node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "node_modules/acorn": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", + "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", "dev": true, - "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" + "license": "MIT", + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": ">=6" + "node": ">=0.4.0" } }, - "node_modules/concurrently/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "node_modules/concurrently/node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "node_modules/acorn-import-phases": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", + "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", "dev": true, - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "acorn": "^8.14.0" } }, - "node_modules/concurrently/node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true + "node_modules/aes-decrypter": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/aes-decrypter/-/aes-decrypter-4.0.2.tgz", + "integrity": "sha512-lc+/9s6iJvuaRe5qDlMTpCFjnwpkeOXp8qP3oiZ5jsj1MRg+SBVUmmICrhxHvc8OELSmc+fEyyxAuppY6hrWzw==", + "license": "Apache-2.0", + "dependencies": { + "@babel/runtime": "^7.12.5", + "@videojs/vhs-utils": "^4.1.1", + "global": "^4.4.0", + "pkcs7": "^1.0.4" + } }, - "node_modules/cosmiconfig": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.1.3.tgz", - "integrity": "sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw==", - "dev": true, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", "dependencies": { - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0" + "debug": "4" }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" + "node": ">= 6.0.0" } }, - "node_modules/crc-32": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz", - "integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==", + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "license": "MIT", "dependencies": { - "exit-on-epipe": "~1.0.1", - "printj": "~1.1.0" - }, - "bin": { - "crc32": "bin/crc32.njs" + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" }, "engines": { - "node": ">=0.8" + "node": ">=8" } }, - "node_modules/cross-fetch": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.6.tgz", - "integrity": "sha512-riRvo06crlE8HiqOwIpQhxwdOk4fOeR7FVM/wXoxchFEqMNUjvbs3bfo4OTgMEMHzppd4DxFBDbyySj8Cv781g==", + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", "dependencies": { - "node-fetch": "^2.6.11" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "dev": true, + "license": "MIT", "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "ajv": "^8.0.0" }, - "engines": { - "node": ">= 8" + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } } }, - "node_modules/css.escape": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", - "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==" - }, - "node_modules/cssstyle": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-3.0.0.tgz", - "integrity": "sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg==", + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "dev": true, + "license": "MIT", "dependencies": { - "rrweb-cssom": "^0.6.0" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" }, - "engines": { - "node": ">=14" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/csstype": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", - "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" }, - "node_modules/cwd": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/cwd/-/cwd-0.10.0.tgz", - "integrity": "sha512-YGZxdTTL9lmLkCUTpg4j0zQ7IhRB5ZmqNBbGCl3Tg6MP/d5/6sY7L5mmTjzbc6JKgVZYiqTQTNhPFsbXNGlRaA==", + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "dev": true, - "dependencies": { - "find-pkg": "^0.1.2", - "fs-exists-sync": "^0.1.0" - }, + "license": "MIT", "engines": { - "node": ">=0.8" + "node": ">=6" } }, - "node_modules/data-urls": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-4.0.0.tgz", - "integrity": "sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g==", - "dev": true, - "dependencies": { - "abab": "^2.0.6", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^12.0.0" - }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", "engines": { - "node": ">=14" + "node": ">=8" } }, - "node_modules/date-fns": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", - "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", - "dev": true, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.21.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=0.11" + "node": ">=8" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", "dependencies": { - "ms": "2.1.2" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">= 8" } }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/decimal.js": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", - "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", - "dev": true - }, - "node_modules/deep-equal": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.1.tgz", - "integrity": "sha512-lKdkdV6EOGoVn65XaOsPdH4rMxTZOnmFyuIkMjM1i5HHCbfjC97dawgTAy0deYNfuqUqW+Q5VrVaQYtUpSd6yQ==", + "node_modules/append-transform": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", + "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", + "dev": true, + "license": "MIT", "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.0", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.2", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.0", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" + "default-require-extensions": "^3.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=8" } }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + "node_modules/archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", + "dev": true, + "license": "MIT" }, - "node_modules/default-require-extensions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.1.tgz", - "integrity": "sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==", + "node_modules/are-docs-informative": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", + "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true, + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true, + "license": "Python-2.0" + }, + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "license": "Apache-2.0", "dependencies": { - "strip-bom": "^4.0.0" + "dequal": "^2.0.3" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dev": true, + "license": "MIT", "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -6383,912 +7858,821 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.4.0" + "node": ">=8" } }, - "node_modules/devtools-protocol": { - "version": "0.0.1120988", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1120988.tgz", - "integrity": "sha512-39fCpE3Z78IaIPChJsP6Lhmkbf4dWXOmzLk/KFTdRkNk/0JymRIfUynDVRndV9HoDz8PyalK1UH21ST/ivwW5Q==", - "dev": true - }, - "node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, "engines": { - "node": ">=0.3.1" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/diff-sequences": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", - "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", "dev": true, + "license": "MIT", "dependencies": { - "path-type": "^4.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", "dev": true, + "license": "MIT", "dependencies": { - "esutils": "^2.0.2" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" }, "engines": { - "node": ">=6.0.0" + "node": ">= 0.4" } }, - "node_modules/dom-accessibility-api": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", - "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==" - }, - "node_modules/domexception": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", - "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", "dev": true, + "license": "MIT", "dependencies": { - "webidl-conversions": "^7.0.0" + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" }, "engines": { - "node": ">=12" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/dotenv": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", - "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=0.10.0" } }, - "node_modules/dotenv-cli": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/dotenv-cli/-/dotenv-cli-7.2.1.tgz", - "integrity": "sha512-ODHbGTskqRtXAzZapDPvgNuDVQApu4oKX8lZW7Y0+9hKA6le1ZJlyRS687oU9FXjOVEDU/VFV6zI125HzhM1UQ==", - "dev": true, + "node_modules/assert": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", + "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", + "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.3", - "dotenv": "^16.0.0", - "dotenv-expand": "^10.0.0", - "minimist": "^1.2.6" - }, - "bin": { - "dotenv": "cli.js" + "call-bind": "^1.0.2", + "is-nan": "^1.3.2", + "object-is": "^1.1.5", + "object.assign": "^4.1.4", + "util": "^0.12.5" } }, - "node_modules/dotenv-expand": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", - "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", + "node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.1" + }, "engines": { - "node": ">=12" + "node": ">=4" } }, - "node_modules/double-ended-queue": { - "version": "2.1.0-0", - "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", - "integrity": "sha512-+BNfZ+deCo8hMNpDqDnvT+c0XpJ5cUa6mqYq89bho2Ifze4URTqRkcwR399hWoTrTkbZ/XJYDgP6rc7pRgffEQ==" - }, - "node_modules/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" }, - "node_modules/electron-to-chromium": { - "version": "1.4.399", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.399.tgz", - "integrity": "sha512-+V1aNvVgoWNWYIbMOiQ1n5fRIaY4SlQ/uRlrsCjLrUwr/3OvQgiX2f5vdav4oArVT9TnttJKcPCqjwPNyZqw/A==", - "dev": true + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "license": "MIT", "dependencies": { - "once": "^1.4.0" + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/engine.io-client": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.4.0.tgz", - "integrity": "sha512-GyKPDyoEha+XZ7iEqam49vz6auPnNJ9ZBfy89f+rMMas8AuiMWOZ9PVzu8xb9ZC6rafUqiGHSCfu22ih66E+1g==", + "node_modules/axios": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.18.1.tgz", + "integrity": "sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==", + "license": "MIT", "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1", - "engine.io-parser": "~5.0.3", - "ws": "~8.11.0", - "xmlhttprequest-ssl": "~2.0.0" + "follow-redirects": "^1.16.0", + "form-data": "^4.0.5", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" } }, - "node_modules/engine.io-client/node_modules/ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "node_modules/babel-loader": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.2.1.tgz", + "integrity": "sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-cache-dir": "^4.0.0", + "schema-utils": "^4.0.0" + }, "engines": { - "node": ">=10.0.0" + "node": ">= 14.15.0" }, "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "@babel/core": "^7.12.0", + "webpack": ">=5" } }, - "node_modules/engine.io-parser": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.6.tgz", - "integrity": "sha512-tjuoZDMAdEhVnSFleYPCtdL2GXwVTGtNjoeJd9IhIG3C1xs9uwxqRNEu5WpnDZCaozwVlK/nuQhpodhXSIMaxw==", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/enhanced-resolve": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.14.0.tgz", - "integrity": "sha512-+DCows0XNwLDcUhbFJPdlQEVnT2zXlCv7hPxemTz86/O+B/hCQ+mb7ydkPKiflpVraqLPCAfu7lDy+hBXueojw==", + "node_modules/babel-loader/node_modules/find-cache-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", + "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "common-path-prefix": "^3.0.0", + "pkg-dir": "^7.0.0" }, "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "engines": { - "node": ">=0.12" + "node": ">=14.16" }, "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/es-abstract": { - "version": "1.21.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", - "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", + "node_modules/babel-loader/node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", "dev": true, + "license": "MIT", "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.0", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.9" + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/es-module-lexer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.2.1.tgz", - "integrity": "sha512-9978wrXM50Y4rTMmW5kXIC09ZdXQZqkE4mxhwkd8VbzsGkXGPgV4zWuqQJgCEzYngdo2dYDa0l8xhX4fkSwJSg==", - "dev": true, - "peer": true - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "node_modules/babel-loader/node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", "dev": true, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" + "p-locate": "^6.0.0" }, "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", - "dev": true, - "dependencies": { - "has": "^1.0.3" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "node_modules/babel-loader/node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", "dev": true, + "license": "MIT", "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "yocto-queue": "^1.0.0" }, "engines": { - "node": ">= 0.4" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true - }, - "node_modules/esbuild": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz", - "integrity": "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==", + "node_modules/babel-loader/node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" + "license": "MIT", + "dependencies": { + "p-limit": "^4.0.0" }, "engines": { - "node": ">=12" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, - "optionalDependencies": { - "@esbuild/android-arm": "0.17.19", - "@esbuild/android-arm64": "0.17.19", - "@esbuild/android-x64": "0.17.19", - "@esbuild/darwin-arm64": "0.17.19", - "@esbuild/darwin-x64": "0.17.19", - "@esbuild/freebsd-arm64": "0.17.19", - "@esbuild/freebsd-x64": "0.17.19", - "@esbuild/linux-arm": "0.17.19", - "@esbuild/linux-arm64": "0.17.19", - "@esbuild/linux-ia32": "0.17.19", - "@esbuild/linux-loong64": "0.17.19", - "@esbuild/linux-mips64el": "0.17.19", - "@esbuild/linux-ppc64": "0.17.19", - "@esbuild/linux-riscv64": "0.17.19", - "@esbuild/linux-s390x": "0.17.19", - "@esbuild/linux-x64": "0.17.19", - "@esbuild/netbsd-x64": "0.17.19", - "@esbuild/openbsd-x64": "0.17.19", - "@esbuild/sunos-x64": "0.17.19", - "@esbuild/win32-arm64": "0.17.19", - "@esbuild/win32-ia32": "0.17.19", - "@esbuild/win32-x64": "0.17.19" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "node_modules/babel-loader/node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/babel-loader/node_modules/pkg-dir": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", + "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^6.3.0" + }, "engines": { - "node": ">=10" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/escodegen": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", - "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", + "node_modules/babel-loader/node_modules/yocto-queue": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", + "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", "dev": true, - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, + "license": "MIT", "engines": { - "node": ">=6.0" + "node": ">=12.20" }, - "optionalDependencies": { - "source-map": "~0.6.1" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/escodegen/node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "node_modules/babylonjs": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/babylonjs/-/babylonjs-9.13.0.tgz", + "integrity": "sha512-wvGqnX+WMG/lZvoNJBY6czpR57sb6RU69cvP7DzZSBkAvaX8gWGTLtiDWYoKltL788KWHSXrbE5CRPplAUGatQ==", "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } + "hasInstallScript": true, + "license": "Apache-2.0" + }, + "node_modules/babylonjs-gltf2interface": { + "version": "6.49.0", + "resolved": "https://registry.npmjs.org/babylonjs-gltf2interface/-/babylonjs-gltf2interface-6.49.0.tgz", + "integrity": "sha512-4qzKCgEayti/YUaeMgAAZxZJlx/kLqXxoC+G8gODYz9wOV9UjnHF09wREZ5cuELzzY/rjSJMqkgDfYbUQIQ6/A==", + "license": "Apache-2.0", + "peer": true }, - "node_modules/escodegen/node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true, - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } + "license": "MIT" }, - "node_modules/escodegen/node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "node_modules/bare-events": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.9.1.tgz", + "integrity": "sha512-Z0oHEHAFDZkffN8Qc39zNZjQlMDkPJRyyyZieU1VH7u8c5S+qHZ2S8ixdKIAxEjfHO7FJxXmJWgteOghVanIsg==", "dev": true, - "engines": { - "node": ">= 0.8.0" + "license": "Apache-2.0", + "peerDependencies": { + "bare-abort-controller": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + } } }, - "node_modules/escodegen/node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "node_modules/bare-fs": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.7.2.tgz", + "integrity": "sha512-aTvMFUWkBmjzKtEQMDGGDNF8bkfpD5N1b/FCwt7A3wrU4t1o/e/85Wzkluh6JlODCjqVESYCkQCdTXqZ9G7VFg==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "prelude-ls": "~1.1.2" + "bare-events": "^2.5.4", + "bare-path": "^3.0.0", + "bare-stream": "^2.6.4", + "bare-url": "^2.2.2", + "fast-fifo": "^1.3.2" }, "engines": { - "node": ">= 0.8.0" + "bare": ">=1.16.0" + }, + "peerDependencies": { + "bare-buffer": "*" + }, + "peerDependenciesMeta": { + "bare-buffer": { + "optional": true + } } }, - "node_modules/eslint": { - "version": "8.41.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.41.0.tgz", - "integrity": "sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==", + "node_modules/bare-os": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.9.1.tgz", + "integrity": "sha512-6M5XjcnsygQNPMCMPXSK379xrJFiZ/AEMNBmFEmQW8d/789VQATvriyi5r0HYTL9TkQ26rn3kgdTG3aisbrXkQ==", "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.3", - "@eslint/js": "8.41.0", - "@humanwhocodes/config-array": "^0.11.8", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.1", - "espree": "^9.5.2", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, + "license": "Apache-2.0", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "bare": ">=1.14.0" } }, - "node_modules/eslint-config-prettier": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", - "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", + "node_modules/bare-path": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.1.tgz", + "integrity": "sha512-ghj2DSK/2e99a1anTVPCV4m4YIYtrbXhfM7V3D7XZLOTsybnYyaJloymGqssQc8l/or0UoDyRtNQkmkEF/ysgQ==", "dev": true, - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" + "license": "Apache-2.0", + "dependencies": { + "bare-os": "^3.0.1" } }, - "node_modules/eslint-plugin-prettier": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", - "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "node_modules/bare-stream": { + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.13.3.tgz", + "integrity": "sha512-Kc+brLqvEqGkjyfiwJmImAOqLZL7OsoLKuavx+hJjgVV3nLTOjloJyPMFxjUPerGGHrNH0fLU06jjykMLWrERQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "prettier-linter-helpers": "^1.0.0" - }, - "engines": { - "node": ">=12.0.0" + "b4a": "^1.8.1", + "streamx": "^2.25.0", + "teex": "^1.0.1" }, "peerDependencies": { - "eslint": ">=7.28.0", - "prettier": ">=2.0.0" + "bare-abort-controller": "*", + "bare-buffer": "*", + "bare-events": "*" }, "peerDependenciesMeta": { - "eslint-config-prettier": { + "bare-abort-controller": { + "optional": true + }, + "bare-buffer": { + "optional": true + }, + "bare-events": { "optional": true } } }, - "node_modules/eslint-plugin-react": { - "version": "7.32.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz", - "integrity": "sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==", + "node_modules/bare-stream/node_modules/b4a": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.1.tgz", + "integrity": "sha512-aiqre1Nr0B/6DgE2N5vwTc+2/oQZ4Wh1t4NznYY4E00y8LCt6NqdRv81so00oo27D8MVKTpUa/MwUUtBLXCoDw==", "dev": true, - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "array.prototype.tosorted": "^1.1.1", - "doctrine": "^2.1.0", - "estraverse": "^5.3.0", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "object.hasown": "^1.1.2", - "object.values": "^1.1.6", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.4", - "semver": "^6.3.0", - "string.prototype.matchall": "^4.0.8" - }, - "engines": { - "node": ">=4" - }, + "license": "Apache-2.0", "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true + } } }, - "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", - "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "node_modules/bare-url": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.4.5.tgz", + "integrity": "sha512-K+y9xF1tN+CdPu4qWwr0QiK1Al07eFPGYK5M2pDXcmHdMdgC/tT/bpmMe1hrmRHaidKLkXrC+cRNYf3XVDUhSQ==", "dev": true, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + "license": "Apache-2.0", + "dependencies": { + "bare-path": "^3.0.0" } }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" }, - "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/baseline-browser-mapping": { + "version": "2.10.38", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.38.tgz", + "integrity": "sha512-31/02mVB4yuQU6adKk5SlY6m+mxDwUq5KZkyYgnLrrKl7TEm1+3PyDtDBz2kOv/wxZz41GHsvV1A/u6RmiyBvw==", "dev": true, + "license": "Apache-2.0", "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "baseline-browser-mapping": "dist/cli.cjs" }, "engines": { - "node": ">=8.0.0" + "node": ">=6.0.0" } }, - "node_modules/eslint-scope/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "node_modules/basic-ftp": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.1.tgz", + "integrity": "sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=4.0" + "node": ">=10.0.0" } }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", + "node_modules/best-random": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/best-random/-/best-random-1.0.3.tgz", + "integrity": "sha512-zrncs76CBFyhE7KVsq85lsc/TT5PUfGTS8arh2aJZcIzQU+WdGNwWYwFsn+w/nuedk04efQdqMy8g5C5pw4shQ==", + "license": "MIT" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, + "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=8" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", - "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", "dev": true, + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "balanced-match": "^1.0.0" } }, - "node_modules/espree": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", - "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", "dependencies": { - "acorn": "^8.8.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "fill-range": "^7.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=8" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } + "license": "ISC" }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "node_modules/browserslist": { + "version": "4.28.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.4.tgz", + "integrity": "sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", "dependencies": { - "estraverse": "^5.1.0" + "baseline-browser-mapping": "^2.10.38", + "caniuse-lite": "^1.0.30001799", + "electron-to-chromium": "^1.5.376", + "node-releases": "^2.0.48", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" }, "engines": { - "node": ">=0.10" + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" } }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=4.0" + "node": "*" } }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/event-stream": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==", + "node_modules/caching-transform": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", + "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", "dev": true, + "license": "MIT", "dependencies": { - "duplexer": "~0.1.1", - "from": "~0", - "map-stream": "~0.1.0", - "pause-stream": "0.0.11", - "split": "0.3", - "stream-combiner": "~0.0.4", - "through": "~2.3.1" + "hasha": "^5.0.0", + "make-dir": "^3.0.0", + "package-hash": "^4.0.0", + "write-file-atomic": "^3.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "node_modules/call-bind": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", + "set-function-length": "^1.2.2" + }, "engines": { - "node": ">=6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, "engines": { - "node": ">=0.8.x" + "node": ">= 0.4" } }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/execa/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/exit-on-epipe": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", - "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==", - "engines": { - "node": ">=0.8" + "node": ">=6" } }, - "node_modules/expand-tilde": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", - "integrity": "sha512-rtmc+cjLZqnu9dSYosX9EWmSJhTwpACgJQTfj4hgg2JjOD/6SIQalZrt4a3aQeh++oNxkazcaxrhPUj6+g5G/Q==", + "node_modules/caniuse-lite": { + "version": "1.0.30001799", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz", + "integrity": "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==", "dev": true, - "dependencies": { - "os-homedir": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" }, - "node_modules/expect": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==", + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", "dependencies": { - "@jest/expect-utils": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/expect-puppeteer": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/expect-puppeteer/-/expect-puppeteer-6.1.1.tgz", - "integrity": "sha512-cnQF96qdoEcOD63j5NQMc0RtW9WRMW/WHKXEKsuDQ2tszhVH3qC7zkXXS4D0LTt9qCB3DEExioqylsQXvqPrUw==", - "dev": true - }, - "node_modules/extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "node_modules/check-more-types": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", + "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", "dev": true, - "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - }, + "license": "MIT", "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" + "node": ">= 0.8.0" } }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, + "license": "MIT", "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" }, "engines": { - "node": ">=8.6.0" + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "node_modules/fast-glob/node_modules/glob-parent": { + "node_modules/chokidar/node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -7296,338 +8680,288 @@ "node": ">= 6" } }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", "dev": true, - "dependencies": { - "pend": "~1.2.0" + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.0" } }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "node_modules/chromium-bidi": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-14.0.0.tgz", + "integrity": "sha512-9gYlLtS6tStdRWzrtXaTMnqcM4dudNegMXJxkR0I/CXObHalYeYcAMPrL19eroNZHtJ8DQmu1E+ZNOYu/IXMXw==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "flat-cache": "^3.0.4" + "mitt": "^3.0.1", + "zod": "^3.24.1" }, - "engines": { - "node": "^10.12.0 || >=12.0.0" + "peerDependencies": { + "devtools-protocol": "*" } }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, + "node_modules/ci-info": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", + "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "node_modules/clean-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", + "integrity": "sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==", "dev": true, + "license": "MIT", "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" + "escape-string-regexp": "^1.0.5" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + "node": ">=4" } }, - "node_modules/find-file-up": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/find-file-up/-/find-file-up-0.1.3.tgz", - "integrity": "sha512-mBxmNbVyjg1LQIIpgO8hN+ybWBgDQK8qjht+EbrTCGmmPV/sc7RF1i9stPTD6bpvXZywBdrwRYxhSdJv867L6A==", + "node_modules/clean-regexp/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, - "dependencies": { - "fs-exists-sync": "^0.1.0", - "resolve-dir": "^0.1.0" - }, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=0.8.0" } }, - "node_modules/find-pkg": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/find-pkg/-/find-pkg-0.1.2.tgz", - "integrity": "sha512-0rnQWcFwZr7eO0513HahrWafsc3CTFioEB7DRiEYCUM/70QXSY8f3mCST17HXLcPvEhzH/Ty/Bxd72ZZsr/yvw==", + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true, - "dependencies": { - "find-file-up": "^0.1.2" - }, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/find-process": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/find-process/-/find-process-1.4.7.tgz", - "integrity": "sha512-/U4CYp1214Xrp3u3Fqr9yNynUrr5Le4y0SsJh2lMDDSbpwYSz3M2SMWQC+wqcx79cN8PQtHQIL8KnuY9M66fdg==", - "dev": true, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "license": "ISC", "dependencies": { - "chalk": "^4.0.0", - "commander": "^5.1.0", - "debug": "^4.1.1" - }, - "bin": { - "find-process": "bin/find-process.js" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" } }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/cluster-key-slot": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.1.tgz", + "integrity": "sha512-rwHwUfXL40Chm1r08yrhU3qpUvdVlgkKNeyeGPOxnW8/SyVDvgRaed/Uz54AqWNaTCAThlj6QAs3TZcKI0xDEw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/code-block-writer": { + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-13.0.3.tgz", + "integrity": "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==", "dev": true, + "license": "MIT" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=7.0.0" } }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" + "delayed-stream": "~1.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">= 0.8" } }, - "node_modules/flat-cache/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "node_modules/fluid-framework": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/fluid-framework/-/fluid-framework-1.3.6.tgz", - "integrity": "sha512-RW+yqWitqAQgX1GsY9pynUEHtQm7Yw5em9BDj29LAzBtLonS4dmqW146qLLD9IJAbF31EfSyBlvLyWHqdqhI6w==", - "dependencies": { - "@fluidframework/container-definitions": "^1.3.6", - "@fluidframework/container-loader": "^1.3.6", - "@fluidframework/driver-definitions": "^1.3.6", - "@fluidframework/fluid-static": "^1.3.6", - "@fluidframework/map": "^1.3.6", - "@fluidframework/sequence": "^1.3.6" + "license": "MIT", + "engines": { + "node": ">=18" } }, - "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], + "node_modules/comment-parser": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", + "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } + "node": ">= 12.0.0" } }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dependencies": { - "is-callable": "^1.1.3" - } + "node_modules/common-path-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", + "dev": true, + "license": "ISC" }, - "node_modules/for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", "dev": true, - "engines": { - "node": ">=0.10.0" - } + "license": "MIT" }, - "node_modules/for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha512-SKmowqGTJoPzLO1T0BBJpkfp3EMacCMOuH40hOUbrbzElVktk4DioXVM99QkLCyKoiuOmyjgcWMpVz2xjE7LZw==", + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", "dev": true, + "license": "MIT", "dependencies": { - "for-in": "^1.0.1" + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/foreground-child": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", - "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", - "dev": true, + "node_modules/crc-32": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz", + "integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==", + "license": "Apache-2.0", "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^3.0.2" + "exit-on-epipe": "~1.0.1", + "printj": "~1.1.0" + }, + "bin": { + "crc32": "bin/crc32.njs" }, "engines": { - "node": ">=8.0.0" + "node": ">=0.8" } }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, "engines": { - "node": ">= 6" + "node": ">= 8" } }, - "node_modules/from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==", - "dev": true - }, - "node_modules/fromentries": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", - "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "license": "MIT" }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" }, - "node_modules/fs-exists-sync": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", - "integrity": "sha512-cR/vflFyPZtrN6b38ZyWxpWdhlXrzZEBawlpBQMq7033xVY7/kg0GDMBK5jg8lDYQckdJ5x/YC88lM3C7VMsLg==", + "node_modules/cwd": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/cwd/-/cwd-0.10.0.tgz", + "integrity": "sha512-YGZxdTTL9lmLkCUTpg4j0zQ7IhRB5ZmqNBbGCl3Tg6MP/d5/6sY7L5mmTjzbc6JKgVZYiqTQTNhPFsbXNGlRaA==", "dev": true, + "license": "MIT", + "dependencies": { + "find-pkg": "^0.1.2", + "fs-exists-sync": "^0.1.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=0.8" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "node_modules/data-uri-to-buffer": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", + "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], + "license": "MIT", "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">= 14" } }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -7636,62 +8970,126 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" } }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "license": "MIT", "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deep-equal": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", + "license": "MIT", "dependencies": { - "pump": "^3.0.0" + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.5", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.2", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-require-extensions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.1.tgz", + "integrity": "sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "strip-bom": "^4.0.0" }, "engines": { "node": ">=8" @@ -7700,14 +9098,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dev": true, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -7716,2357 +9115,2618 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" }, "engines": { - "node": "*" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "node_modules/degenerator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", "dev": true, + "license": "MIT", "dependencies": { - "is-glob": "^4.0.3" + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" }, "engines": { - "node": ">=10.13.0" + "node": ">= 14" } }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true, - "peer": true + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } }, - "node_modules/global-modules": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", - "integrity": "sha512-JeXuCbvYzYXcwE6acL9V2bAOeSIGl4dD+iwLY9iUx2VBJJ80R18HCn+JCwHM9Oegdfya3lEkGCdaRkSyc10hDA==", - "dev": true, - "dependencies": { - "global-prefix": "^0.1.4", - "is-windows": "^0.2.0" - }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "license": "Apache-2.0", "engines": { - "node": ">=0.10.0" + "node": ">=0.10" } }, - "node_modules/global-prefix": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", - "integrity": "sha512-gOPiyxcD9dJGCEArAhF4Hd0BAqvAe/JzERP7tYumE4yIkmIedPUVXcJFWbV3/p/ovIIvKjkrTk+f1UVkq7vvbw==", - "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.0", - "ini": "^1.3.4", - "is-windows": "^0.2.0", - "which": "^1.2.12" - }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/global-prefix/node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true + "node_modules/devtools-protocol": { + "version": "0.0.1608973", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1608973.tgz", + "integrity": "sha512-Tpm17fxYzt+J7VrGdc1k8YdRqS3YV7se/M6KeemEqvUbq/n7At1rWVuXMxQgpWkdwSdIEKYbU//Bve+Shm4YNQ==", + "dev": true, + "license": "BSD-3-Clause" }, - "node_modules/global-prefix/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "node_modules/diff": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz", + "integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==", "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" } }, - "node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, + "license": "MIT", "dependencies": { - "type-fest": "^0.20.2" + "path-type": "^4.0.0" }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "define-properties": "^1.1.3" + "esutils": "^2.0.2" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=6.0.0" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "license": "MIT" + }, + "node_modules/dom-walk": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" + }, + "node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, + "license": "BSD-2-Clause", "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://dotenvx.com" } }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "node_modules/dotenv-cli": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/dotenv-cli/-/dotenv-cli-7.4.4.tgz", + "integrity": "sha512-XkBYCG0tPIes+YZr4SpfFv76SQrV/LeCE8CI7JSEMi3VR9MvTihCGTOtbIexD6i2mXF+6px7trb1imVCXSNMDw==", + "dev": true, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.1.3" + "cross-spawn": "^7.0.6", + "dotenv": "^16.3.0", + "dotenv-expand": "^10.0.0", + "minimist": "^1.2.6" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "bin": { + "dotenv": "cli.js" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, - "node_modules/grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true + "node_modules/dotenv-expand": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", + "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true + "node_modules/double-ended-queue": { + "version": "2.1.0-0", + "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", + "integrity": "sha512-+BNfZ+deCo8hMNpDqDnvT+c0XpJ5cUa6mqYq89bho2Ifze4URTqRkcwR399hWoTrTkbZ/XJYDgP6rc7pRgffEQ==", + "license": "MIT" }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", "dependencies": { - "function-bind": "^1.1.1" + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" }, "engines": { - "node": ">= 0.4.0" + "node": ">= 0.4" } }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.378", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.378.tgz", + "integrity": "sha512-VinvOAuuPmdD1guEgGv5f2Qp7/vlfqOrUOMYNnOD4wj3pit8kRsQHzfIf6teyUGWo15Tg5+bOJaRunvyltpVWQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/embla-carousel": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.6.0.tgz", + "integrity": "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA==", + "license": "MIT" + }, + "node_modules/embla-carousel-autoplay": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/embla-carousel-autoplay/-/embla-carousel-autoplay-8.6.0.tgz", + "integrity": "sha512-OBu5G3nwaSXkZCo1A6LTaFMZ8EpkYbwIaH+bPqdBnDGQ2fh4+NbzjXjs2SktoPNKCtflfVMc75njaDHOYXcrsA==", + "license": "MIT", + "peerDependencies": { + "embla-carousel": "8.6.0" } }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" + "node_modules/embla-carousel-fade": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/embla-carousel-fade/-/embla-carousel-fade-8.6.0.tgz", + "integrity": "sha512-qaYsx5mwCz72ZrjlsXgs1nKejSrW+UhkbOMwLgfRT7w2LtdEB03nPRI06GHuHv5ac2USvbEiX2/nAHctcDwvpg==", + "license": "MIT", + "peerDependencies": { + "embla-carousel": "8.6.0" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "once": "^1.4.0" } }, - "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/engine.io-client": { + "version": "6.6.6", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.6.tgz", + "integrity": "sha512-iY6QdftLQ9pyiPoX082bpf/u1UewnOaJrtJIF9T0++QB34lZrj0uP+Q/bj8AlUsAxqhnkTV2BS8SBZSxOmoV5Q==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.4.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.21.0", + "xmlhttprequest-ssl": "~2.1.1" } }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "node_modules/engine.io-client/node_modules/ws": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", + "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=10.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dependencies": { - "has-symbols": "^1.0.2" - }, + "node_modules/engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10.0.0" } }, - "node_modules/hasha": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", - "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", + "node_modules/enhanced-resolve": { + "version": "5.24.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.1.tgz", + "integrity": "sha512-7DdUaTjmNwMcH2gLr1qycesKII3BK4RLy/mdAb7x10Lq7bR4aNKHt1BR1ZALSv0rPM/hF5wYF0PhGop/rJm8vw==", "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "is-stream": "^2.0.0", - "type-fest": "^0.8.0" + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=10.13.0" } }, - "node_modules/hasha/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "dev": true, - "bin": { - "he": "bin/he" + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" } }, - "node_modules/homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "node_modules/es-abstract": { + "version": "1.24.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", + "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", "dev": true, + "license": "MIT", "dependencies": { - "parse-passwd": "^1.0.0" + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/html-encoding-sniffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", - "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "node_modules/es-abstract-get": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-abstract-get/-/es-abstract-get-1.0.0.tgz", + "integrity": "sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg==", "dev": true, + "license": "MIT", "dependencies": { - "whatwg-encoding": "^2.0.0" + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.2", + "is-callable": "^1.2.7", + "object-inspect": "^1.13.4" }, "engines": { - "node": ">=12" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } }, - "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "license": "MIT", "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" }, - "engines": { - "node": ">= 6" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "node_modules/es-iterator-helpers": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.3.3.tgz", + "integrity": "sha512-0PuBxFi+4uPanB97iDxCLWuHeYud2FALrw5HFZGtAF38UpJDbDC8frwp2cnDyae692CQ0dou60UwWfhgsa4U/g==", "dev": true, + "license": "MIT", "dependencies": { - "agent-base": "6", - "debug": "4" + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.1.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.3.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.5", + "math-intrinsics": "^1.1.0" }, "engines": { - "node": ">= 6" + "node": ">= 0.4" } }, - "node_modules/human-signals": { + "node_modules/es-module-lexer": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", + "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, "engines": { - "node": ">=10.17.0" + "node": ">= 0.4" } }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, "engines": { - "node": ">= 4" + "node": ">= 0.4" } }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "node_modules/es-to-primitive": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.1.tgz", + "integrity": "sha512-CxN9N56HYfd2m/acc/NOFrZQsN9kU4eh+2kk6A707Kz1krH8tKmfrs5RnftB8WNX80T0NS7vSQsDOlg23diR2g==", "dev": true, + "license": "MIT", "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "es-abstract-get": "^1.0.0", + "es-errors": "^1.3.0", + "is-callable": "^1.2.7", + "is-date-object": "^1.1.0", + "is-symbol": "^1.1.1" }, "engines": { - "node": ">=6" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "dev": true, - "engines": { - "node": ">=0.8.19" - } + "license": "MIT" }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" }, "engines": { - "node": ">= 0.4" + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" } }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" }, "engines": { - "node": ">= 0.4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/eslint" } }, - "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "node_modules/eslint-config-biome": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/eslint-config-biome/-/eslint-config-biome-2.1.3.tgz", + "integrity": "sha512-IL720kAN79egw8KyaoZsC0UMLn+NlVdPeX2ZmL0CIEcQdLJCf6d1ELCQTKnJ9Lpe6dzfP5ZF8yZ0PTMOirtT+w==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint-config-prettier": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.2.tgz", + "integrity": "sha512-iI1f+D2ViGn+uvv5HuHVUamg8ll4tN+JRHGc6IJi4TP9Kl976C57fzPXgseXNs8v0iA8aSJpHsTWjDb9QJamGQ==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "eslint": ">=7.0.0" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "node_modules/eslint-import-context": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/eslint-import-context/-/eslint-import-context-0.1.9.tgz", + "integrity": "sha512-K9Hb+yRaGAGUbwjhFNHvSmmkZs9+zbuoe3kFQ4V1wYjrepUFYM2dZAfNtjbbj3qsPfUfsA68Bx/ICWQMi+C8Eg==", + "dev": true, + "license": "MIT", "dependencies": { - "has-bigints": "^1.0.1" + "get-tsconfig": "^4.10.1", + "stable-hash-x": "^0.2.0" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/eslint-import-context" + }, + "peerDependencies": { + "unrs-resolver": "^1.0.0" + }, + "peerDependenciesMeta": { + "unrs-resolver": { + "optional": true + } } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "node_modules/eslint-plugin-eslint-comments": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.2.0.tgz", + "integrity": "sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==", "dev": true, + "license": "MIT", "dependencies": { - "binary-extensions": "^2.0.0" + "escape-string-regexp": "^1.0.5", + "ignore": "^5.0.5" }, "engines": { - "node": ">=8" + "node": ">=6.5.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=4.19.1" } }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "node_modules/eslint-plugin-eslint-comments/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint-plugin-jsdoc": { + "version": "55.0.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-55.0.5.tgz", + "integrity": "sha512-foZ/+Fm20JCYmP5msD4MpmFb0MxajkVJ15YMKxvQ7WJK0zI/iykkClpsuqbav3bLtDhaOalYxwRx0pGTqoQoRA==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "@es-joy/jsdoccomment": "~0.56.0", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.4.1", + "debug": "^4.4.1", + "escape-string-regexp": "^4.0.0", + "espree": "^10.4.0", + "esquery": "^1.6.0", + "object-deep-merge": "^1.0.5", + "parse-imports-exports": "^0.2.4", + "semver": "^7.7.2", + "spdx-expression-parse": "^4.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=20.11.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, - "node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "node_modules/eslint-plugin-jsdoc/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">= 0.4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/eslint" } }, - "node_modules/is-core-module": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", - "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", + "node_modules/eslint-plugin-jsdoc/node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "has": "^1.0.3" + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/eslint" } }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "node_modules/eslint-plugin-prettier": { + "version": "5.5.6", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.6.tgz", + "integrity": "sha512-ifetmTcxWfz+4qRW3pH/ujdTq2jQIj59AxJMIN26K5avYgU8dxycUETQonWiW+wPrYXA0j3Try0l1CnwVQtDqQ==", + "dev": true, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "prettier-linter-helpers": "^1.0.1", + "synckit": "^0.11.13" }, "engines": { - "node": ">= 0.4" + "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } } }, - "node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "node_modules/eslint-plugin-promise": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-7.2.1.tgz", + "integrity": "sha512-SWKjd+EuvWkYaS+uN2csvj0KoP43YTu7+phKQ5v+xw6+A0gutVX2yqCeCkC3uLCJFiPfR2dD8Es5L7yUsmvEaA==", "dev": true, + "license": "ISC", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0" + }, "engines": { - "node": ">=0.10.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "node_modules/eslint-plugin-react": { + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "node_modules/eslint-plugin-react/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, + "license": "MIT", "dependencies": { - "is-extglob": "^2.1.1" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "node_modules/eslint-plugin-react/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, - "engines": { - "node": ">= 0.4" + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "*" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "node_modules/eslint-plugin-tsdoc": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.4.0.tgz", + "integrity": "sha512-MT/8b4aKLdDClnS8mP3R/JNjg29i0Oyqd/0ym6NnQf+gfKbJJ4ZcSh2Bs1H0YiUMTBwww5JwXGTWot/RwyJ7aQ==", + "dev": true, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@microsoft/tsdoc": "0.15.1", + "@microsoft/tsdoc-config": "0.17.1" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "node_modules/eslint-plugin-unicorn": { + "version": "48.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-48.0.1.tgz", + "integrity": "sha512-FW+4r20myG/DqFcCSzoumaddKBicIPeFnTrifon2mWIzlfyvzwyqZjqVP7m4Cqr/ZYisS2aiLghkUWaPg6vtCw==", "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.5", + "@eslint-community/eslint-utils": "^4.4.0", + "ci-info": "^3.8.0", + "clean-regexp": "^1.0.0", + "esquery": "^1.5.0", + "indent-string": "^4.0.0", + "is-builtin-module": "^3.2.1", + "jsesc": "^3.0.2", + "lodash": "^4.17.21", + "pluralize": "^8.0.0", + "read-pkg-up": "^7.0.1", + "regexp-tree": "^0.1.27", + "regjsparser": "^0.10.0", + "semver": "^7.5.4", + "strip-indent": "^3.0.0" + }, "engines": { - "node": ">=8" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sindresorhus/eslint-plugin-unicorn?sponsor=1" + }, + "peerDependencies": { + "eslint": ">=8.44.0" } }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "node_modules/eslint-plugin-unicorn/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "node_modules/eslint-plugin-unused-imports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-3.2.0.tgz", + "integrity": "sha512-6uXyn6xdINEpxE1MtDjxQsyXB37lfyO2yKGVVgtD7WEWQGORSOZjgrD6hBhvGv4/SO+TOlS+UnC6JppRqbuwGQ==", "dev": true, + "license": "MIT", "dependencies": { - "isobject": "^3.0.1" + "eslint-rule-composer": "^0.3.0" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "engines": { - "node": ">= 0.4" + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "6 - 7", + "eslint": "8" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + } } }, - "node_modules/is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/eslint-rule-composer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz", + "integrity": "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0.0" } }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "call-bind": "^1.0.2" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/eslint" } }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", "dependencies": { - "has-symbols": "^1.0.2" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "*" } }, - "node_modules/is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": ">= 0.4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/eslint" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, - "engines": { - "node": ">=10" + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=4" } }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "call-bind": "^1.0.2" + "estraverse": "^5.1.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=0.10" } }, - "node_modules/is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "estraverse": "^5.2.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=4.0" } }, - "node_modules/is-windows": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", - "integrity": "sha512-n67eJYmXbniZB7RF4I/FTjK1s6RPOCTxhYrVYLRaCt3lF0mpWZPKr3T2LSZAqyjQsxR2qMmGYXXzK0YWwcPM1Q==", + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "engines": { - "node": ">=0.10.0" + "node": ">=4.0" } }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "node_modules/event-stream": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==", "dev": true, + "license": "MIT", + "dependencies": { + "duplexer": "~0.1.1", + "from": "~0", + "map-stream": "~0.1.0", + "pause-stream": "0.0.11", + "split": "0.3", + "stream-combiner": "~0.0.4", + "through": "~2.3.1" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=0.8.x" } }, - "node_modules/istanbul-lib-hook": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", - "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", - "dev": true, - "dependencies": { - "append-transform": "^2.0.0" - }, + "node_modules/events_pkg": { + "name": "events", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=0.8.x" } }, - "node_modules/istanbul-lib-instrument": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", - "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "node_modules/events-universal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", + "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/core": "^7.7.5", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" + "bare-events": "^2.7.0" } }, - "node_modules/istanbul-lib-processinfo": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz", - "integrity": "sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==", + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, + "license": "MIT", "dependencies": { - "archy": "^1.0.0", "cross-spawn": "^7.0.3", - "istanbul-lib-coverage": "^3.2.0", - "p-map": "^3.0.0", - "rimraf": "^3.0.0", - "uuid": "^8.3.2" + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/istanbul-lib-processinfo/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "node_modules/execa/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" + "license": "MIT", + "engines": { + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/istanbul-lib-processinfo/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" + "node_modules/exit-on-epipe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", + "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" } }, - "node_modules/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "node_modules/expand-tilde": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", + "integrity": "sha512-rtmc+cjLZqnu9dSYosX9EWmSJhTwpACgJQTfj4hgg2JjOD/6SIQalZrt4a3aQeh++oNxkazcaxrhPUj6+g5G/Q==", "dev": true, + "license": "MIT", "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" + "os-homedir": "^1.0.1" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, + "node_modules/expect": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.4.1.tgz", + "integrity": "sha512-PMARsyh/JtqC20HoGqlFcIlQAyqUtW4PlI1rup1uhYJtKuwAjbvWi3GQMAn+STdHum/dk8xrKfUM1+5SAwpolA==", + "license": "MIT", "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" + "@jest/expect-utils": "30.4.1", + "@jest/get-type": "30.1.0", + "jest-matcher-utils": "30.4.1", + "jest-message-util": "30.4.1", + "jest-mock": "30.4.1", + "jest-util": "30.4.1" }, "engines": { - "node": ">=10" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", + "node_modules/expect-puppeteer": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/expect-puppeteer/-/expect-puppeteer-11.0.0.tgz", + "integrity": "sha512-fgxsbOD+HqwOCMitYqEDzRoJM2fxKbCKPYfUoukK+qdZm/nC+cTOI74Au2MfmMZmF/5CgQGO4+1Ywq2GgD8zCQ==", "dev": true, - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/jest-dev-server": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jest-dev-server/-/jest-dev-server-6.2.0.tgz", - "integrity": "sha512-ZWh8CuvxwjhYfvw4tGeftziqIvw/26R6AG3OTgNTQeXul8aZz48RQjDpnlDwnWX53jxJJl9fcigqIdSU5lYZuw==", + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "chalk": "^4.1.2", - "cwd": "^0.10.0", - "find-process": "^1.4.7", - "prompts": "^2.4.2", - "spawnd": "^6.2.0", - "tree-kill": "^1.2.2", - "wait-on": "^6.0.1" - } - }, - "node_modules/jest-diff": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", - "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.4.3", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-diff/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "engines": { - "node": ">=10" + "node": ">= 10.17.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "optionalDependencies": { + "@types/yauzl": "^2.9.1" } }, - "node_modules/jest-diff/node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", - "dependencies": { - "@jest/schemas": "^29.4.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" }, - "node_modules/jest-diff/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true, + "license": "Apache-2.0" }, - "node_modules/jest-environment-node": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", - "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=8.6.0" } }, - "node_modules/jest-environment-node/node_modules/@jest/types": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", - "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^16.0.0", - "chalk": "^4.0.0" + "is-glob": "^4.0.1" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">= 6" } }, - "node_modules/jest-environment-node/node_modules/@types/yargs": { - "version": "16.0.5", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.5.tgz", - "integrity": "sha512-AxO/ADJOBFJScHbWhq2xAhlWP24rY4aCEG/NFaMvbT3X2MgRsLjhjQwsn0Zi5zn0LG9jUhCCZMeX9Dkuw6k+vQ==", + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true, - "dependencies": { - "@types/yargs-parser": "*" - } + "license": "MIT" }, - "node_modules/jest-environment-node/node_modules/jest-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", - "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", "dependencies": { - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "reusify": "^1.0.4" } }, - "node_modules/jest-environment-puppeteer": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jest-environment-puppeteer/-/jest-environment-puppeteer-6.2.0.tgz", - "integrity": "sha512-a/oSu6dO9D+XoDDe3ZY/0Sk79Jl2FcJl7Q0D+3x22l1eWNOYe4ikXnPGhtmNZ3mJIpuAVIX6LytA8EraOk/aqQ==", + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", "dev": true, + "license": "MIT", "dependencies": { - "chalk": "^4.1.2", - "cwd": "^0.10.0", - "jest-dev-server": "^6.2.0", - "jest-environment-node": "^27.5.1", - "merge-deep": "^3.0.3" + "pend": "~1.2.0" } }, - "node_modules/jest-get-type": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", - "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } } }, - "node_modules/jest-matcher-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz", - "integrity": "sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==", + "node_modules/fengari": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/fengari/-/fengari-0.1.5.tgz", + "integrity": "sha512-0DS4Nn4rV8qyFlQCpKK8brT61EUtswynrpfFTcgLErcilBIBskSMQ86fO2WVuybr14ywyKdRjv91FiRZwnEuvQ==", + "license": "MIT", "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^29.5.0", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "readline-sync": "^1.4.10", + "sprintf-js": "^1.1.3", + "tmp": "^0.2.5" } }, - "node_modules/jest-matcher-utils/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node_modules/fengari-interop": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/fengari-interop/-/fengari-interop-0.1.4.tgz", + "integrity": "sha512-4/CW/3PJUo3ebD4ACgE1g/3NGEYSq7OQAyETyypsAl/WeySDBbxExikkayNkZzbpgyC9GyJp8v1DU2VOXxNq7Q==", + "license": "MIT", + "peerDependencies": { + "fengari": "^0.1.0" } }, - "node_modules/jest-matcher-utils/node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", "dependencies": { - "@jest/schemas": "^29.4.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "flat-cache": "^3.0.4" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/jest-matcher-utils/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" - }, - "node_modules/jest-message-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.5.0.tgz", - "integrity": "sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==", + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.5.0", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.5.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" + "to-regex-range": "^5.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/jest-message-util/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "license": "MIT", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" } }, - "node_modules/jest-message-util/node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "node_modules/find-file-up": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/find-file-up/-/find-file-up-0.1.3.tgz", + "integrity": "sha512-mBxmNbVyjg1LQIIpgO8hN+ybWBgDQK8qjht+EbrTCGmmPV/sc7RF1i9stPTD6bpvXZywBdrwRYxhSdJv867L6A==", + "dev": true, + "license": "MIT", "dependencies": { - "@jest/schemas": "^29.4.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "fs-exists-sync": "^0.1.0", + "resolve-dir": "^0.1.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/jest-message-util/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" - }, - "node_modules/jest-mock": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", - "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "node_modules/find-pkg": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/find-pkg/-/find-pkg-0.1.2.tgz", + "integrity": "sha512-0rnQWcFwZr7eO0513HahrWafsc3CTFioEB7DRiEYCUM/70QXSY8f3mCST17HXLcPvEhzH/Ty/Bxd72ZZsr/yvw==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/types": "^27.5.1", - "@types/node": "*" + "find-file-up": "^0.1.2" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=0.10.0" } }, - "node_modules/jest-mock/node_modules/@jest/types": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", - "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "node_modules/find-process": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/find-process/-/find-process-1.4.11.tgz", + "integrity": "sha512-mAOh9gGk9WZ4ip5UjV0o6Vb4SrfnAmtsFNzkMRH9HQiFXVQnDyQFrSHTK5UoG6E+KV+s+cIznbtwpfN41l2nFA==", "dev": true, + "license": "MIT", "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^16.0.0", - "chalk": "^4.0.0" + "chalk": "~4.1.2", + "commander": "^12.1.0", + "loglevel": "^1.9.2" }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "bin": { + "find-process": "bin/find-process.js" } }, - "node_modules/jest-mock/node_modules/@types/yargs": { - "version": "16.0.5", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.5.tgz", - "integrity": "sha512-AxO/ADJOBFJScHbWhq2xAhlWP24rY4aCEG/NFaMvbT3X2MgRsLjhjQwsn0Zi5zn0LG9jUhCCZMeX9Dkuw6k+vQ==", + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "license": "MIT", "dependencies": { - "@types/yargs-parser": "*" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-puppeteer": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jest-puppeteer/-/jest-puppeteer-6.2.0.tgz", - "integrity": "sha512-4Ynkgcf9FkHlTNEpdsojGLb3KtsToWqjO6SCigxb9Qj3HzIqhzJzNbDJ/XhiciNDpqDe6KHW9sZ6fjHphNLr6g==", + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true, - "dependencies": { - "expect-puppeteer": "^6.1.1", - "jest-environment-puppeteer": "^6.2.0" - }, - "peerDependencies": { - "puppeteer": ">= 1.5.0" + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" } }, - "node_modules/jest-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", - "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", "dependencies": { - "@jest/types": "^29.5.0", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "node_modules/flatted": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", "dev": true, - "peer": true, + "license": "ISC" + }, + "node_modules/fluid-framework": { + "version": "2.110.0", + "resolved": "https://registry.npmjs.org/fluid-framework/-/fluid-framework-2.110.0.tgz", + "integrity": "sha512-6bU/5bsnvSrgOX+aHItxogNE5GHeucy/61JIFrZZ+rMeCqbyqaYb2weRTZqz2WhwDKi8ykUgkvfKP6yYFfhphw==", + "license": "MIT", "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, + "@fluidframework/container-definitions": "~2.110.0", + "@fluidframework/container-loader": "~2.110.0", + "@fluidframework/core-interfaces": "~2.110.0", + "@fluidframework/core-utils": "~2.110.0", + "@fluidframework/driver-definitions": "~2.110.0", + "@fluidframework/fluid-static": "~2.110.0", + "@fluidframework/map": "~2.110.0", + "@fluidframework/runtime-utils": "~2.110.0", + "@fluidframework/sequence": "~2.110.0", + "@fluidframework/shared-object-base": "~2.110.0", + "@fluidframework/tree": "~2.110.0" + } + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", "engines": { - "node": ">= 10.13.0" + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } } }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "peer": true, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "is-callable": "^1.2.7" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/joi": { - "version": "17.9.2", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.9.2.tgz", - "integrity": "sha512-Itk/r+V4Dx0V3c7RLFdRh12IOjySm2/WGPMubBT92cQvRfYZhPM2W0hZlctjj72iES8jsRCwp7S/cRmWBnJ4nw==", - "dev": true, - "dependencies": { - "@hapi/hoek": "^9.0.0", - "@hapi/topo": "^5.0.0", - "@sideway/address": "^4.1.3", - "@sideway/formula": "^3.0.1", - "@sideway/pinpoint": "^2.0.0" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "node_modules/foreground-child": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", "dev": true, + "license": "ISC", "dependencies": { - "argparse": "^2.0.1" + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">=8.0.0" } }, - "node_modules/jsdom": { - "version": "21.1.2", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-21.1.2.tgz", - "integrity": "sha512-sCpFmK2jv+1sjff4u7fzft+pUh2KSUbUrEHYHyfSIbGTIcmnjyp83qg6qLwdJ/I3LpTXx33ACxeRL7Lsyc6lGQ==", - "dev": true, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "license": "MIT", "dependencies": { - "abab": "^2.0.6", - "acorn": "^8.8.2", - "acorn-globals": "^7.0.0", - "cssstyle": "^3.0.0", - "data-urls": "^4.0.0", - "decimal.js": "^10.4.3", - "domexception": "^4.0.0", - "escodegen": "^2.0.0", - "form-data": "^4.0.0", - "html-encoding-sniffer": "^3.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.1", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.4", - "parse5": "^7.1.2", - "rrweb-cssom": "^0.6.0", - "saxes": "^6.0.0", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.1.2", - "w3c-xmlserializer": "^4.0.0", - "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^2.0.0", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^12.0.1", - "ws": "^8.13.0", - "xml-name-validator": "^4.0.0" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "canvas": "^2.5.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } + "node": ">= 6" } }, - "node_modules/jsdom-global": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsdom-global/-/jsdom-global-3.0.2.tgz", - "integrity": "sha512-t1KMcBkz/pT5JrvcJbpUR2u/w1kO9jXctaaGJ0vZDzwFnIvGWw9IDSRciT83kIs8Bnw4qpOl8bQK08V01YgMPg==", + "node_modules/from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==", "dev": true, - "peerDependencies": { - "jsdom": ">=10.0.0" - } + "license": "MIT" }, - "node_modules/jsdom/node_modules/ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "node_modules/fromentries": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", + "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" }, - "utf-8-validate": { - "optional": true + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" } - } + ], + "license": "MIT" }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "node_modules/fs-exists-sync": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", + "integrity": "sha512-cR/vflFyPZtrN6b38ZyWxpWdhlXrzZEBawlpBQMq7033xVY7/kg0GDMBK5jg8lDYQckdJ5x/YC88lM3C7VMsLg==", "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, - "bin": { - "json5": "lib/cli.js" - }, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", - "dev": true - }, - "node_modules/jsrsasign": { - "version": "10.8.6", - "resolved": "https://registry.npmjs.org/jsrsasign/-/jsrsasign-10.8.6.tgz", - "integrity": "sha512-bQmbVtsfbgaKBTWCKiDCPlUPbdlRIK/FzSwT3BzIgZl/cU6TqXu6pZJsCI/dJVrZ9Gir5GC4woqw9shH/v7MBw==", + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", "funding": { - "url": "https://github.com/kjur/jsrsasign#donations" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jsx-ast-utils": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", - "integrity": "sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==", + "node_modules/function.prototype.name": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.2.0.tgz", + "integrity": "sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==", "dev": true, + "license": "MIT", "dependencies": { - "array-includes": "^3.1.5", - "object.assign": "^4.1.3" + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2", + "hasown": "^2.0.4", + "is-callable": "^1.2.7", + "is-document.all": "^1.0.0" }, "engines": { - "node": ">=4.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jwt-decode": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", - "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==" - }, - "node_modules/keyborg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/keyborg/-/keyborg-2.0.0.tgz", - "integrity": "sha512-RWY8nWrzRkwTQLaKyDtbTu5SOb5L4B20UzAsBHlQDFZqVY/+Mid0bQ7MVTC8vbOTrWY2xkkzj8gZF9Ua7re4xA==" - }, - "node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "license": "MIT", "engines": { - "node": ">=6" + "node": ">= 0.4" } }, - "node_modules/lazy-ass": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", - "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==", + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, + "license": "MIT", "engines": { - "node": "> 0.8" + "node": ">=6.9.0" } }, - "node_modules/lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ==", - "dev": true, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", "engines": { - "node": ">=0.10.0" + "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/live-canvas-tests": { - "resolved": "samples/typescript/31.live-canvas-tests", - "link": true - }, - "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true, - "peer": true, + "license": "MIT", "engines": { - "node": ">=6.11.5" + "node": ">=8.0.0" } }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, + "license": "MIT", "dependencies": { - "p-locate": "^5.0.0" + "pump": "^3.0.0" }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash.flattendeep": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", - "dev": true - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", "dev": true, + "license": "MIT", "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "node_modules/get-tsconfig": { + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz", + "integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==", + "dev": true, + "license": "MIT", "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" + "resolve-pkg-maps": "^1.0.0" }, - "bin": { - "loose-envify": "cli.js" + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "node_modules/get-uri": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.5.tgz", + "integrity": "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==", "dev": true, + "license": "MIT", "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/lunr": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", - "dev": true - }, - "node_modules/lz-string": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", - "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", - "bin": { - "lz-string": "bin/bin.js" + "basic-ftp": "^5.0.2", + "data-uri-to-buffer": "^6.0.2", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" } }, - "node_modules/magic-string": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz", - "integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==", + "node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, + "license": "ISC", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.13" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" }, "engines": { "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", "dependencies": { - "semver": "^6.0.0" + "is-glob": "^4.0.3" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=10.13.0" } }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "node_modules/map-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==", - "dev": true + "license": "BSD-2-Clause", + "peer": true }, - "node_modules/marked": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", - "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "node_modules/glob/node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", "dev": true, - "bin": { - "marked": "bin/marked.js" + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">= 12" + "node": ">=10" } }, - "node_modules/merge-deep": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/merge-deep/-/merge-deep-3.0.3.tgz", - "integrity": "sha512-qtmzAS6t6grwEkNrunqTBdn0qKwFgNWvlxUbAV8es9M7Ot1EbyApytCnvE0jALPa46ZpKDUo527kKiaWplmlFA==", + "node_modules/global": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", + "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", + "license": "MIT", + "dependencies": { + "min-document": "^2.19.0", + "process": "^0.11.10" + } + }, + "node_modules/global-modules": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", + "integrity": "sha512-JeXuCbvYzYXcwE6acL9V2bAOeSIGl4dD+iwLY9iUx2VBJJ80R18HCn+JCwHM9Oegdfya3lEkGCdaRkSyc10hDA==", "dev": true, + "license": "MIT", "dependencies": { - "arr-union": "^3.1.0", - "clone-deep": "^0.2.4", - "kind-of": "^3.0.2" + "global-prefix": "^0.1.4", + "is-windows": "^0.2.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "node_modules/global-prefix": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", + "integrity": "sha512-gOPiyxcD9dJGCEArAhF4Hd0BAqvAe/JzERP7tYumE4yIkmIedPUVXcJFWbV3/p/ovIIvKjkrTk+f1UVkq7vvbw==", "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "license": "MIT", "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" + "homedir-polyfill": "^1.0.0", + "ini": "^1.3.4", + "is-windows": "^0.2.0", + "which": "^1.2.12" }, "engines": { - "node": ">=8.6" + "node": ">=0.10.0" } }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "node_modules/global-prefix/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true, - "engines": { - "node": ">= 0.6" - } + "license": "ISC" }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, + "license": "ISC", "dependencies": { - "mime-db": "1.52.0" + "isexe": "^2.0.0" }, - "engines": { - "node": ">= 0.6" + "bin": { + "which": "bin/which" } }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, "engines": { - "node": ">=6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, "engines": { - "node": ">=4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" }, "engines": { - "node": "*" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mitt": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.0.tgz", - "integrity": "sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==", - "dev": true + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" }, - "node_modules/mixin-object": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", - "integrity": "sha512-ALGF1Jt9ouehcaXaHhn6t1yGWRqGaHkPFndtFVHfZXOvkIZ/yoGaSi0AHVTafb3ZBGg4dr/bDwnaEKqCXzchMA==", + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true, - "dependencies": { - "for-in": "^0.1.3", - "is-extendable": "^0.1.1" - }, + "license": "MIT" + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mixin-object/node_modules/for-in": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", - "integrity": "sha512-F0to7vbBSHP8E3l6dCjxNOLuSFAACIxFy3UehTUlG7svlXi37HHsDkyVcHo0Pq8QwrE+pXvWSVX3ZT1T9wAZ9g==", - "dev": true, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", "dependencies": { - "minimist": "^1.2.6" + "es-define-property": "^1.0.0" }, - "bin": { - "mkdirp": "bin/cmd.js" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "dev": true - }, - "node_modules/mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", - "dev": true, - "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" }, "engines": { - "node": ">= 14.0.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.1" + "has-symbols": "^1.0.3" }, "engines": { - "node": ">=10" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/hasha": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", + "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", "dev": true, + "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "is-stream": "^2.0.0", + "type-fest": "^0.8.0" }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", + "node_modules/hasha/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, + "license": "(MIT OR CC0-1.0)", "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": ">=8" } }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, - "node_modules/nconf": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/nconf/-/nconf-0.12.0.tgz", - "integrity": "sha512-T3fZPw3c7Dfrz8JBQEbEcZJ2s8f7cUMpKuyBtsGQe0b71pcXx6gNh4oti2xh5dxB+gO9ufNfISBlGvvWtfyMcA==", - "dev": true, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", "dependencies": { - "async": "^3.0.0", - "ini": "^2.0.0", - "secure-keys": "^1.0.0", - "yargs": "^16.1.1" + "function-bind": "^1.1.2" }, "engines": { - "node": ">= 0.4.0" + "node": ">= 0.4" } }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, - "peer": true + "license": "MIT", + "bin": { + "he": "bin/he" + } }, - "node_modules/node-fetch": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "license": "MIT", "dependencies": { - "whatwg-url": "^5.0.0" + "parse-passwd": "^1.0.0" }, "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } + "node": ">=0.10.0" } }, - "node_modules/node-fetch/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true, + "license": "ISC" }, - "node_modules/node-fetch/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" }, - "node_modules/node-fetch/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" } }, - "node_modules/node-preload": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", - "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", "dependencies": { - "process-on-spawn": "^1.0.0" + "agent-base": "6", + "debug": "4" }, "engines": { - "node": ">=8" + "node": ">= 6" } }, - "node_modules/node-releases": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", - "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", - "dev": true + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + "license": "MIT", + "engines": { + "node": ">= 4" } }, - "node_modules/normalize-package-data/node_modules/resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, + "license": "MIT", "dependencies": { - "is-core-module": "^2.11.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, - "bin": { - "resolve": "bin/resolve" + "engines": { + "node": ">=6" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, - "bin": { - "semver": "bin/semver" + "license": "MIT", + "engines": { + "node": ">=0.8.19" } }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, + "license": "ISC", "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" + "once": "^1.3.0", + "wrappy": "1" } }, - "node_modules/nwsapi": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.4.tgz", - "integrity": "sha512-NHj4rzRo0tQdijE9ZqAx6kYDcoRwYwSYzCA8MY3JzfxlrvEU0jhnhJT9BhqhJs7I/dKcrDm6TyulaRqZPIhN5g==", - "dev": true + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" }, - "node_modules/nyc": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", - "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", - "dev": true, + "node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "license": "MIT", "dependencies": { - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "caching-transform": "^4.0.0", - "convert-source-map": "^1.7.0", - "decamelize": "^1.2.0", - "find-cache-dir": "^3.2.0", - "find-up": "^4.1.0", - "foreground-child": "^2.0.0", - "get-package-type": "^0.1.0", - "glob": "^7.1.6", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-hook": "^3.0.0", - "istanbul-lib-instrument": "^4.0.0", - "istanbul-lib-processinfo": "^2.0.2", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.2", - "make-dir": "^3.0.0", - "node-preload": "^0.2.1", - "p-map": "^3.0.0", - "process-on-spawn": "^1.0.0", - "resolve-from": "^5.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "spawn-wrap": "^2.0.0", - "test-exclude": "^6.0.0", - "yargs": "^15.0.2" - }, - "bin": { - "nyc": "bin/nyc.js" + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" }, "engines": { - "node": ">=8.9" + "node": ">= 0.4" } }, - "node_modules/nyc/node_modules/cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, + "node_modules/ioredis": { + "version": "5.11.1", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.11.1.tgz", + "integrity": "sha512-ehuGcf94bQXhfagULNXrJdfnWO38v070jxSx/qE87Kjzmu2fU7ro5EFAb+OPituLqgfyuQaym5DlrNydW2sJ9A==", + "license": "MIT", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" + "@ioredis/commands": "1.10.0", + "cluster-key-slot": "1.1.1", + "debug": "4.4.3", + "denque": "2.1.0", + "redis-errors": "1.2.0", + "redis-parser": "3.0.0", + "standard-as-callback": "2.1.0" + }, + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ioredis" } }, - "node_modules/nyc/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, + "node_modules/ioredis-mock": { + "version": "8.13.1", + "resolved": "https://registry.npmjs.org/ioredis-mock/-/ioredis-mock-8.13.1.tgz", + "integrity": "sha512-Wsi50AU+cMiI32nAgfwpUaJVBtb4iQdVsOHl9M6R3tePCO/8vGsToCVIG82XWAxN4Se55TZoOzVseu+QngFLyw==", + "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "@ioredis/as-callback": "^3.0.0", + "@ioredis/commands": "^1.4.0", + "fengari": "^0.1.4", + "fengari-interop": "^0.1.3", + "semver": "^7.7.2" }, "engines": { - "node": ">=8" + "node": ">=12.22" + }, + "peerDependencies": { + "@types/ioredis-mock": "^8", + "ioredis": "^5" } }, - "node_modules/nyc/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/ip-address": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", + "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==", "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 12" } }, - "node_modules/nyc/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, + "node_modules/is-arguments": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" }, "engines": { - "node": ">=6" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/nyc/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "license": "MIT", "dependencies": { - "p-limit": "^2.2.0" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/nyc/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true, - "engines": { - "node": ">=8" - } + "license": "MIT" }, - "node_modules/nyc/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", "dev": true, + "license": "MIT", "dependencies": { - "glob": "^7.1.3" + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, - "bin": { - "rimraf": "bin.js" + "engines": { + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/nyc/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "has-bigints": "^1.0.2" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/nyc/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "node_modules/nyc/node_modules/yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, + "license": "MIT", "dependencies": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" + "binary-extensions": "^2.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/nyc/node_modules/yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "license": "MIT", "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { - "node": ">=6" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "node_modules/is-builtin-module": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", + "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", + "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "builtin-modules": "^3.3.0" }, "engines": { - "node": ">= 0.4" + "node": ">=6" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "engines": { - "node": ">= 0.4" + "node_modules/is-bun-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.7.1" } }, - "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -10074,29 +11734,32 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object.entries": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", - "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "hasown": "^2.0.3" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object.fromentries": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", - "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -10105,28 +11768,30 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object.hasown": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", - "integrity": "sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==", - "dev": true, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "license": "MIT", "dependencies": { - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "node_modules/is-document.all": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-document.all/-/is-document.all-1.0.0.tgz", + "integrity": "sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bound": "^1.0.4" }, "engines": { "node": ">= 0.4" @@ -10135,424 +11800,554 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, - "dependencies": { - "wrappy": "1" + "license": "MIT", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", "dev": true, + "license": "MIT", "dependencies": { - "mimic-fn": "^2.1.0" + "call-bound": "^1.0.3" }, "engines": { - "node": ">=6" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", "engines": { - "node": ">= 0.8.0" + "node": ">=8" } }, - "node_modules/os-homedir": { + "node_modules/is-function": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", + "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==", + "license": "MIT" }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "license": "MIT", "dependencies": { - "yocto-queue": "^0.1.0" + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "license": "MIT", "dependencies": { - "p-limit": "^3.0.2" + "is-extglob": "^2.1.1" }, "engines": { - "node": ">=10" + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/p-map": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", - "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", - "dev": true, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "license": "MIT", "dependencies": { - "aggregate-error": "^3.0.0" + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/package-hash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", - "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "dependencies": { - "graceful-fs": "^4.1.15", - "hasha": "^5.0.0", - "lodash.flattendeep": "^4.4.0", - "release-zalgo": "^1.0.0" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=0.12.0" } }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "license": "MIT", "dependencies": { - "callsites": "^3.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { - "node": ">=6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, + "license": "MIT", "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dev": true, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "license": "MIT", "dependencies": { - "entities": "^4.4.0" + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==" - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==", - "dev": true, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "license": "MIT", "dependencies": { - "through": "~2.3" + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/picocolors": { + "node_modules/is-typedarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true, + "license": "MIT" }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=8.6" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "license": "MIT", "engines": { - "node": ">=4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", "dev": true, + "license": "MIT", "dependencies": { - "find-up": "^4.0.0" + "call-bound": "^1.0.3" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-windows": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", + "integrity": "sha512-n67eJYmXbniZB7RF4I/FTjK1s6RPOCTxhYrVYLRaCt3lF0mpWZPKr3T2LSZAqyjQsxR2qMmGYXXzK0YWwcPM1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=8" } }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/istanbul-lib-hook": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", + "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "p-locate": "^4.1.0" + "append-transform": "^2.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/istanbul-lib-instrument": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "p-try": "^2.0.0" + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-processinfo": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz", + "integrity": "sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==", "dev": true, + "license": "ISC", "dependencies": { - "p-limit": "^2.2.0" + "archy": "^1.0.0", + "cross-spawn": "^7.0.3", + "istanbul-lib-coverage": "^3.2.0", + "p-map": "^3.0.0", + "rimraf": "^3.0.0", + "uuid": "^8.3.2" }, "engines": { "node": ">=8" } }, - "node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "node_modules/istanbul-lib-processinfo/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "^10 || ^12 || >=14" + "node": ">=10" } }, - "node_modules/postcss/node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "node_modules/istanbul-lib-report/node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, "engines": { - "node": ">= 0.8.0" + "node": ">=10" } }, - "node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", "dev": true, - "bin": { - "prettier": "bin-prettier.js" + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" }, "engines": { - "node": ">=10.13.0" + "node": ">=8" + } + }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "engines": { + "node": ">= 0.4" } }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "node_modules/jest-dev-server": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/jest-dev-server/-/jest-dev-server-11.0.0.tgz", + "integrity": "sha512-a54rw3uEzsPckyiXo2rPji9R/5z0d0qhXtru+NwCP8cDxOFk/BIP9PNgmcLh0DU8UTl8s6Lg1u+ri5uQsTJTmw==", "dev": true, + "license": "MIT", "dependencies": { - "fast-diff": "^1.1.2" + "chalk": "^4.1.2", + "cwd": "^0.10.0", + "find-process": "^1.4.7", + "prompts": "^2.4.2", + "spawnd": "^11.0.0", + "tree-kill": "^1.2.2", + "wait-on": "^8.0.1" }, "engines": { - "node": ">=6.0.0" + "node": ">=18" } }, - "node_modules/pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "node_modules/jest-diff": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.4.1.tgz", + "integrity": "sha512-CRpFK0RtLriVDGcPPAnR6HMVI8bSR2jnUIgralhauzYQZIb4RH9AtEInTuQr65LmmGggGcRT6HIASxwqsVsmlA==", + "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" + "@jest/diff-sequences": "30.4.0", + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "pretty-format": "30.4.1" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/pretty-format/node_modules/ansi-styles": { + "node_modules/jest-diff/node_modules/ansi-styles": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -10560,1322 +12355,1486 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/printj": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", - "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==", - "bin": { - "printj": "bin/printj.njs" + "node_modules/jest-diff/node_modules/pretty-format": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.4.1.tgz", + "integrity": "sha512-K6KiKMHTL4jjX4u3Kir2EW07nRfcqVTXIImx50wbjHQTcZPgg+gjVeNTIT3l3L1Rd4UefxfogquC9J37SoFyyw==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "30.4.1", + "ansi-styles": "^5.2.0", + "react-is-18": "npm:react-is@^18.3.1", + "react-is-19": "npm:react-is@^19.2.5" }, "engines": { - "node": ">=0.8" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/process-on-spawn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", - "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", "dev": true, + "license": "MIT", "dependencies": { - "fromentries": "^1.2.0" + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "node_modules/jest-environment-node/node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, "engines": { - "node": ">=0.4.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "node_modules/jest-environment-node/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, + "license": "MIT", "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" }, "engines": { - "node": ">= 6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } + "node_modules/jest-environment-node/node_modules/@sinclair/typebox": { + "version": "0.27.10", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz", + "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==", + "dev": true, + "license": "MIT" }, - "node_modules/prop-types/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/proper-lockfile": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", - "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "node_modules/jest-environment-node/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "retry": "^0.12.0", - "signal-exit": "^3.0.2" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" } }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true - }, - "node_modules/ps-tree": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", - "integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==", + "node_modules/jest-environment-node/node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "dev": true, + "license": "MIT", "dependencies": { - "event-stream": "=3.3.4" - }, - "bin": { - "ps-tree": "bin/ps-tree.js" + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" }, "engines": { - "node": ">= 0.10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "node_modules/jest-environment-node/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "license": "MIT", "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "node_modules/jest-environment-node/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/puppeteer": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-20.3.0.tgz", - "integrity": "sha512-OJIsxC3PcU6fAWfp1BX0oKj62FFxhxwpakGAcGVbyfqfDrNmkFjpzb0XrMsgnQxCJmoLpTZKHRXDFxEDnLqkow==", + "node_modules/jest-environment-puppeteer": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/jest-environment-puppeteer/-/jest-environment-puppeteer-11.0.0.tgz", + "integrity": "sha512-BJR+k19/awJmXVc5IJ3VY+tho0888PvHAp16D+DP/ezRL84bgg4ggc1Q3mfa85DI+Nw9hgTme3pt0X5F7CWxmg==", "dev": true, - "hasInstallScript": true, + "license": "MIT", "dependencies": { - "@puppeteer/browsers": "1.3.0", - "cosmiconfig": "8.1.3", - "puppeteer-core": "20.3.0" + "chalk": "^4.1.2", + "cosmiconfig": "^8.3.6", + "deepmerge": "^4.3.1", + "jest-dev-server": "^11.0.0", + "jest-environment-node": "^29.7.0" + }, + "engines": { + "node": ">=18" } }, - "node_modules/puppeteer-core": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-20.3.0.tgz", - "integrity": "sha512-264pBrIui5bO6NJeOcbJrLa0OCwmA4+WK00JMrLIKTfRiqe2gx8KWTzLsjyw/bizErp3TKS7vt/I0i5fTC+mAw==", - "dev": true, + "node_modules/jest-matcher-utils": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.4.1.tgz", + "integrity": "sha512-zvYfX5CaeEkFrrLS9suWe9rvJrm9J1Iv3ua8kIBv9GEPzcnsfBf0bob37la7s67fs0nlBC3EuvkOLnXQKxtx4A==", + "license": "MIT", "dependencies": { - "@puppeteer/browsers": "1.3.0", - "chromium-bidi": "0.4.9", - "cross-fetch": "3.1.6", - "debug": "4.3.4", - "devtools-protocol": "0.0.1120988", - "ws": "8.13.0" + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "jest-diff": "30.4.1", + "pretty-format": "30.4.1" }, "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "typescript": ">= 4.7.4" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/puppeteer-core/node_modules/ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", - "dev": true, + "node_modules/jest-matcher-utils/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "license": "MIT", "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" + "node": ">=10" }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/querystring": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz", - "integrity": "sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==", - "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "node_modules/jest-matcher-utils/node_modules/pretty-format": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.4.1.tgz", + "integrity": "sha512-K6KiKMHTL4jjX4u3Kir2EW07nRfcqVTXIImx50wbjHQTcZPgg+gjVeNTIT3l3L1Rd4UefxfogquC9J37SoFyyw==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "30.4.1", + "ansi-styles": "^5.2.0", + "react-is-18": "npm:react-is@^18.3.1", + "react-is-19": "npm:react-is@^19.2.5" + }, "engines": { - "node": ">=0.4.x" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "node_modules/jest-message-util": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.4.1.tgz", + "integrity": "sha512-kwCKIvq0MCW1HzLoGola9Te6JUdzgV0loyKJ3Qghrkz9i5/RRIHsL95BMQc2HBBhlBKC4j22K9p11TGHH8RBpQ==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.4.1", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "jest-util": "30.4.1", + "picomatch": "^4.0.3", + "pretty-format": "30.4.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } }, - "node_modules/random-js": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/random-js/-/random-js-1.0.8.tgz", - "integrity": "sha512-LznfUohEMi6jfwZXa0C5uY1p1tciZozzMiwf9LGlwj52tfvpHozYklHHkrvh2Ya/mdiJ9qPGXR6byVN7+hCMTw==", - "dev": true + "node_modules/jest-message-util/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, + "node_modules/jest-message-util/node_modules/pretty-format": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.4.1.tgz", + "integrity": "sha512-K6KiKMHTL4jjX4u3Kir2EW07nRfcqVTXIImx50wbjHQTcZPgg+gjVeNTIT3l3L1Rd4UefxfogquC9J37SoFyyw==", + "license": "MIT", "dependencies": { - "safe-buffer": "^5.1.0" + "@jest/schemas": "30.4.1", + "ansi-styles": "^5.2.0", + "react-is-18": "npm:react-is@^18.3.1", + "react-is-19": "npm:react-is@^19.2.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/react": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", - "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "node_modules/jest-mock": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.4.1.tgz", + "integrity": "sha512-/i8SVb8/NSB7RfNi8gfqu8gxLV23KaL5EpAttyb9iz8qWRIqXRLflycz/32wXsYkOnaUlx8NAKnJYtpsmXUmfw==", + "license": "MIT", "dependencies": { - "loose-envify": "^1.1.0" + "@jest/types": "30.4.1", + "@types/node": "*", + "jest-util": "30.4.1" }, "engines": { - "node": ">=0.10.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/react-babylonjs": { - "version": "3.1.20", - "resolved": "https://registry.npmjs.org/react-babylonjs/-/react-babylonjs-3.1.20.tgz", - "integrity": "sha512-+5xZxcVJtKd7mHZqDb0njzmGR8IXuAl2pAtWqOfFkmSYA4Hn+nWC1qrGw3xpZMqFYkw+uu0coFZL431zNlyoNQ==", + "node_modules/jest-puppeteer": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/jest-puppeteer/-/jest-puppeteer-11.0.0.tgz", + "integrity": "sha512-kixkUTNcXikldQ+TusIEvqtTO/et/MiXGkoUBQViPSdSN6JOPvTjDN/mo6Jh4EJzay8qFg/Sd4v4gPS0y9b+zw==", + "dev": true, + "license": "MIT", "dependencies": { - "react-reconciler": "^0.27.0" + "expect-puppeteer": "^11.0.0", + "jest-environment-puppeteer": "^11.0.0" }, "engines": { - "node": ">=14.0.0" + "node": ">=18" }, "peerDependencies": { - "@babylonjs/core": "5.x || 6.x", - "@babylonjs/gui": "5.x || 6.x", - "react": ">=18", - "react-dom": ">=18" - }, - "peerDependenciesMeta": { - "react-dom": { - "optional": true - } + "puppeteer": ">=19" } }, - "node_modules/react-colorful": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz", - "integrity": "sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==", - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" + "node_modules/jest-regex-util": { + "version": "30.4.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.4.0.tgz", + "integrity": "sha512-mWlvLviKIgIQ8VCuM1xRdD0TWp3zlzionlmDBjuXVBs+VkmXq6FgW9T4Emr7oGz/Rk6feDCGyiugolcQEyp3mg==", + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/react-dom": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", - "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "node_modules/jest-util": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.4.1.tgz", + "integrity": "sha512-vjQb1sACEiv13DKJMDToJpzVW0joCsIQrmbg0fi7CyOOt+g9jTuQl2A216pWRBYhOVt53XbL/2LbMKg1BECWOw==", + "license": "MIT", "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.0" + "@jest/types": "30.4.1", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.3" }, - "peerDependencies": { - "react": "^18.2.0" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/react-dom/node_modules/scheduler": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", - "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "loose-envify": "^1.1.0" + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" } }, - "node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" - }, - "node_modules/react-media-template-ts": { - "resolved": "samples/typescript/21.react-media-template", - "link": true - }, - "node_modules/react-reconciler": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.27.0.tgz", - "integrity": "sha512-HmMDKciQjYmBRGuuhIaKA1ba/7a+UsM5FzOZsMO2JYHt9Jh8reCb7j1eDC95NOyUlKM9KRyvdx0flBuDvYSBoA==", + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.21.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" }, - "peerDependencies": { - "react": "^18.0.0" + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/react-reconciler/node_modules/scheduler": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.21.0.tgz", - "integrity": "sha512-1r87x5fz9MXqswA2ERLo0EbOAU74DpIUO090gIasYTqlVoJeMcl+Z1Rg7WHz+qtPujhS/hGIt9kxZOYBV3faRQ==", - "dependencies": { - "loose-envify": "^1.1.0" - } + "node_modules/jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", + "dev": true, + "license": "MIT" }, - "node_modules/react-refresh": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", - "integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==", + "node_modules/joi": { + "version": "18.2.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-18.2.3.tgz", + "integrity": "sha512-N5A3KTWQpPWT4ExxxPlUx7WmykGXRzhNidWhV41d6Abu9YfI2NyWCJuxdPnslJCPWtbRpSVOWSnSS6GakLM/Rg==", "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/address": "^5.1.1", + "@hapi/formula": "^3.0.2", + "@hapi/hoek": "^11.0.7", + "@hapi/pinpoint": "^2.0.1", + "@hapi/tlds": "^1.1.1", + "@hapi/topo": "^6.0.2", + "@standard-schema/spec": "^1.1.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 20" } }, - "node_modules/react-router": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.11.2.tgz", - "integrity": "sha512-74z9xUSaSX07t3LM+pS6Un0T55ibUE/79CzfZpy5wsPDZaea1F8QkrsiyRnA2YQ7LwE/umaydzXZV80iDCPkMg==", + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", + "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", "dependencies": { - "@remix-run/router": "1.6.2" + "argparse": "^2.0.1" }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsdoc-type-pratt-parser": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-5.1.1.tgz", + "integrity": "sha512-DYYlVP1fe4QBMh2xTIs20/YeTz2GYVbWAEZweHSZD+qQ/Cx2d5RShuhhsdk64eTjNq0FeVnteP/qVOgaywSRbg==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=14" - }, - "peerDependencies": { - "react": ">=16.8" + "node": ">=12.0.0" } }, - "node_modules/react-router-dom": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.11.2.tgz", - "integrity": "sha512-JNbKtAeh1VSJQnH6RvBDNhxNwemRj7KxCzc5jb7zvDSKRnPWIFj9pO+eXqjM69gQJ0r46hSz1x4l9y0651DKWw==", - "dependencies": { - "@remix-run/router": "1.6.2", - "react-router": "6.11.2" + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "react": ">=16.8", - "react-dom": ">=16.8" + "node": ">=6" } }, - "node_modules/react-video": { - "resolved": "samples/javascript/02.react-video", - "link": true + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "license": "ISC" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" }, "engines": { - "node": ">= 6" + "node": ">=6" } }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "node_modules/jsrsasign": { + "version": "11.1.3", + "resolved": "https://registry.npmjs.org/jsrsasign/-/jsrsasign-11.1.3.tgz", + "integrity": "sha512-nPnK5D/4lv0Dwr7TlzrKtAd8JlLZwFTqTUUB3NQCbtdobcRcohGFxjbPySDVh74iWUudcCsapYT6OxoyhJLhhA==", + "license": "MIT" + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", "dev": true, + "license": "MIT", "dependencies": { - "picomatch": "^2.2.1" + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" }, "engines": { - "node": ">=8.10.0" + "node": ">=4.0" } }, - "node_modules/redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dependencies": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - }, + "node_modules/jwt-decode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + "node_modules/keyborg": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/keyborg/-/keyborg-2.14.1.tgz", + "integrity": "sha512-/WmmVBa6Me3hIKAOIyIq1sql+6oydQZzGMBDLNfOcJ8710byMsq3KSLS8GQhBJHOMtvnXnUBrDAIbABcZVipcg==", + "license": "MIT" }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", - "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "json-buffer": "3.0.1" } }, - "node_modules/release-zalgo": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", - "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==", + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true, - "dependencies": { - "es6-error": "^4.0.1" - }, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=6" } }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "node_modules/lazy-ass": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", + "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": "> 0.8" } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8.0" } }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + "node_modules/live-canvas-tests": { + "resolved": "samples/typescript/31.live-canvas-tests", + "link": true }, - "node_modules/resolve": { - "version": "2.0.0-next.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", - "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", + "node_modules/loader-runner": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz", + "integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==", "dev": true, - "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.11.5" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/resolve-dir": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", - "integrity": "sha512-QxMPqI6le2u0dCLyiGzgy92kjkkL6zO0XyvHzjdTNH3zM6e5Hz3BwG6+aEyNgiQ5Xz6PwTwgQEj3U50dByPKIA==", + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, + "license": "MIT", "dependencies": { - "expand-tilde": "^1.2.2", - "global-modules": "^0.2.3" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "license": "MIT" + }, + "node_modules/lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", "dev": true, - "engines": { - "node": ">=4" - } + "license": "MIT" }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true, - "engines": { - "node": ">= 4" - } + "license": "MIT" }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "node_modules/loglevel": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.2.tgz", + "integrity": "sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==", "dev": true, - "dependencies": { - "glob": "^7.1.3" + "license": "MIT", + "engines": { + "node": ">= 0.6.0" }, - "bin": { - "rimraf": "bin.js" + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/loglevel" } }, - "node_modules/rollup": { - "version": "3.28.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.28.0.tgz", - "integrity": "sha512-d7zhvo1OUY2SXSM6pfNjgD5+d0Nz87CUp4mt8l/GgVP3oBsPwzNvSzyu1me6BSG9JIgWNTVcafIXBIyM8yQ3yw==", - "dev": true, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=14.18.0", - "npm": ">=8.0.0" + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "bin": { + "loose-envify": "cli.js" } }, - "node_modules/rrweb-cssom": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", - "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==", - "dev": true - }, - "node_modules/rtl-css-js": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.1.tgz", - "integrity": "sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==", + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", "dependencies": { - "@babel/runtime": "^7.1.2" + "yallist": "^3.0.2" } }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "license": "MIT", + "bin": { + "lz-string": "bin/bin.js" } }, - "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, + "node_modules/lz4js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/lz4js/-/lz4js-0.2.0.tgz", + "integrity": "sha512-gY2Ia9Lm7Ep8qMiuGRhvUq0Q7qUereeldZPP1PMEJxPtEWHJLqw9pgX68oHajBH0nzJK4MaZEA/YNV3jT8u8Bg==", + "license": "ISC" + }, + "node_modules/m3u8-parser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/m3u8-parser/-/m3u8-parser-7.2.0.tgz", + "integrity": "sha512-CRatFqpjVtMiMaKXxNvuI3I++vUumIXVVT/JpCpdU/FynV/ceVw1qpPyyBNindL+JlPMSesx+WX1QJaZEJSaMQ==", + "license": "Apache-2.0", "dependencies": { - "tslib": "^2.1.0" + "@babel/runtime": "^7.12.5", + "@videojs/vhs-utils": "^4.1.1", + "global": "^4.4.0" } }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } }, - "node_modules/saxes": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", - "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true, - "dependencies": { - "xmlchars": "^2.2.0" - }, + "license": "ISC" + }, + "node_modules/map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==", + "dev": true + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", "engines": { - "node": ">=v12.22.7" + "node": ">= 0.4" } }, - "node_modules/scheduler": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", - "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" }, - "node_modules/schema-utils": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.1.tgz", - "integrity": "sha512-lELhBAAly9NowEsX0yZBlw9ahZG+sK/1RJ21EpzdYHKEs13Vku3LJ+MIPhh4sMs0oCCeufZQEQbMekiA4vuVIQ==", + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, + "license": "MIT", "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">= 8" } }, - "node_modules/schema-utils/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, + "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "braces": "^3.0.3", + "picomatch": "^2.3.1" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": ">=8.6" } }, - "node_modules/schema-utils/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" + "license": "MIT", + "engines": { + "node": ">=8.6" }, - "peerDependencies": { - "ajv": "^8.8.2" + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/schema-utils/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/secure-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/secure-keys/-/secure-keys-1.0.0.tgz", - "integrity": "sha512-nZi59hW3Sl5P3+wOO89eHBAAGwmCPd2aE1+dLZV5MO+ItQctIvAqihzaAXIQhvtH4KJPxM080HsnqltR2y8cWg==", - "dev": true + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } }, - "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "mime-db": "1.52.0" }, "engines": { - "node": ">=10" + "node": ">= 0.6" } }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=6" } }, - "node_modules/semver/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "node_modules/min-document": { + "version": "2.19.2", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.2.tgz", + "integrity": "sha512-8S5I8db/uZN8r9HSLFVWPdJCvYOejMcEC82VIzNUc6Zkklf/d1gg2psfE79/vyhWOj4+J8MtwmoOz3TmvaGu5A==", + "license": "MIT", + "dependencies": { + "dom-walk": "^0.1.0" + } }, - "node_modules/serialize-error": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-8.1.0.tgz", - "integrity": "sha512-3NnuWfM6vBYoy5gZFvHiYsVbafvI9vZv/+jlIigFn4oP4zjNPK3LhcY0xSCgeb1a5L8jO71Mit9LlNoi2UfDDQ==", + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, + "license": "ISC", "dependencies": { - "type-fest": "^0.20.2" + "brace-expansion": "^2.0.2" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true + "node_modules/minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=8" + } }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "dev": true, + "license": "MIT" + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "license": "MIT", "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "minimist": "^1.2.6" }, "bin": { - "sha.js": "bin.js" + "mkdirp": "bin/cmd.js" } }, - "node_modules/shallow-clone": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-0.1.2.tgz", - "integrity": "sha512-J1zdXCky5GmNnuauESROVu31MQSnLoYvlyEn6j2Ztk6Q5EHFIhxkMhYcv6vuDzl2XEzoRr856QwzMgWM/TmZgw==", + "node_modules/mocha": { + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz", + "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==", "dev": true, + "license": "MIT", "dependencies": { - "is-extendable": "^0.1.1", - "kind-of": "^2.0.1", - "lazy-cache": "^0.2.3", - "mixin-object": "^2.0.1" + "ansi-colors": "^4.1.3", + "browser-stdout": "^1.3.1", + "chokidar": "^3.5.3", + "debug": "^4.3.5", + "diff": "^5.2.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^8.1.0", + "he": "^1.2.0", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^5.1.6", + "ms": "^2.1.3", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^6.5.1", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.9", + "yargs-unparser": "^2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" }, "engines": { - "node": ">=0.10.0" + "node": ">= 14.0.0" } }, - "node_modules/shallow-clone/node_modules/kind-of": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", - "integrity": "sha512-0u8i1NZ/mg0b+W3MGGw5I7+6Eib2nx72S/QvXa0hYjEkjTknYmEYQJwGu3mLC0BrhtJjtQafTkyRUQ75Kx0LVg==", + "node_modules/mocha-json-output-reporter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mocha-json-output-reporter/-/mocha-json-output-reporter-2.1.0.tgz", + "integrity": "sha512-FF2BItlMo8nK9+SgN/WAD01ue7G+qI1Po0U3JCZXQiiyTJ5OV3KcT1mSoZKirjYP73JFZznaaPC6Mp052PF3Vw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "mocha": "^10.0.0", + "moment": "^2.21.0" + } + }, + "node_modules/mocha-multi-reporters": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/mocha-multi-reporters/-/mocha-multi-reporters-1.5.1.tgz", + "integrity": "sha512-Yb4QJOaGLIcmB0VY7Wif5AjvLMUFAdV57D2TWEva1Y0kU/3LjKpeRVmlMIfuO1SVbauve459kgtIizADqxMWPg==", "dev": true, + "license": "MIT", "dependencies": { - "is-buffer": "^1.0.2" + "debug": "^4.1.1", + "lodash": "^4.17.15" }, "engines": { - "node": ">=0.10.0" + "node": ">=6.0.0" + }, + "peerDependencies": { + "mocha": ">=3.1.2" } }, - "node_modules/shallow-clone/node_modules/lazy-cache": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz", - "integrity": "sha512-gkX52wvU/R8DVMMt78ATVPFMJqfW8FPz1GZ1sVHBVQHmu/WvhIWE4cE1GBzhJNFicDeYhnwp6Rl35BcAIM3YOQ==", + "node_modules/mocha/node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", "dependencies": { - "shebang-regex": "^3.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", "dev": true, + "license": "MIT", + "peer": true, "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/shiki": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.2.tgz", - "integrity": "sha512-ltSZlSLOuSY0M0Y75KA+ieRaZ0Trf5Wl3gutE7jzLuIcWxLp5i/uEnLoQWNvgKXQ5OMpGkJnVMRLAuzjc0LJ2A==", - "dev": true, + "node_modules/mpd-parser": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-1.4.0.tgz", + "integrity": "sha512-blbA7XpAaOdC/PR0Tu8GiUxlx6CpBuRowQPYV7lhi9Yr9G9+dkPXIUjqjzc/NCn/uZZPopluaJlIYntIEI/VLw==", + "license": "Apache-2.0", "dependencies": { - "ansi-sequence-parser": "^1.1.0", - "jsonc-parser": "^3.2.0", - "vscode-oniguruma": "^1.7.0", - "vscode-textmate": "^8.0.0" + "@babel/runtime": "^7.12.5", + "@videojs/vhs-utils": "^4.1.2", + "@xmldom/xmldom": "^0.8.3", + "global": "^4.4.0" + }, + "bin": { + "mpd-to-m3u8-json": "bin/parse.js" } }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/mux.js": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/mux.js/-/mux.js-7.1.0.tgz", + "integrity": "sha512-NTxawK/BBELJrYsZThEulyUMDVlLizKdxyAsMuzoCD1eFj97BVaA8D/CvKsKu6FOLYkFojN5CbM9h++ZTZtknA==", + "license": "Apache-2.0", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "@babel/runtime": "^7.11.2", + "global": "^4.4.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "bin": { + "muxjs-transmux": "bin/transmux.js" + }, + "engines": { + "node": ">=8", + "npm": ">=5" } }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/sillyname": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/sillyname/-/sillyname-0.1.0.tgz", - "integrity": "sha512-GWA0Zont13ov+cMNw4T7nU4SCyW8jdhD3vjA5+qs8jr+09sCPxOf+FPS5zE0c9pYlCwD+NU/CiMimY462lgG9g==" - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "node_modules/nanoid": { + "version": "3.3.15", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.15.tgz", + "integrity": "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, "engines": { - "node": ">=8" + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/socket.io-client": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.6.1.tgz", - "integrity": "sha512-5UswCV6hpaRsNg5kkEHVcbBIXEYoVbMQaHJBXJCyEQ+CiFPV1NIOY0XOFWG4XR4GZcB8Kn6AsRs/9cy9TbqVMQ==", - "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.2", - "engine.io-client": "~6.4.0", - "socket.io-parser": "~4.2.1" + "node_modules/napi-postinstall": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" }, "engines": { - "node": ">=10.0.0" + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" } }, - "node_modules/socket.io-parser": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.3.tgz", - "integrity": "sha512-JMafRntWVO2DCJimKsRTh/wnqVvO4hrfwOqtO7f+uzwsQMuxO6VwImtYxaQ+ieoyshWOTJyV0fA21lccEXRPpQ==", + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/nconf": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/nconf/-/nconf-0.12.1.tgz", + "integrity": "sha512-p2cfF+B3XXacQdswUYWZ0w6Vld0832A/tuqjLBu3H1sfUcby4N2oVbGhyuCkZv+t3iY3aiFEj7gZGqax9Q2c1w==", + "license": "MIT", "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1" + "async": "^3.0.0", + "ini": "^2.0.0", + "secure-keys": "^1.0.0", + "yargs": "^16.1.1" }, "engines": { - "node": ">=10.0.0" + "node": ">= 0.4.0" } }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true, - "engines": { - "node": ">=0.10.0" - } + "license": "MIT", + "peer": true }, - "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "node_modules/netmask": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.1.1.tgz", + "integrity": "sha512-eonl3sLUha+S1GzTPxychyhnUzKyeQkZ7jLjKrBagJgPla13F+uQ71HgpFefyHgqrjEbCPkDArxYsjY8/+gLKA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 0.4.0" } }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "node_modules/node-exports-info": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.2.tgz", + "integrity": "sha512-kXs9Go0cah0qHVV2v389IXQLdLCeE1xfFtjOAF+iobu0OIoG1pje8At2vMHyaPMiPMnG/LWP50twML21eMcAag==", "dev": true, + "license": "MIT", "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "array.prototype.flatmap": "^1.3.3", + "es-errors": "^1.3.0", + "object.entries": "^1.1.9", + "semver": "^6.3.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/spawn-command": { - "version": "0.0.2-1", - "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", - "integrity": "sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==", - "dev": true + "node_modules/node-exports-info/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } }, - "node_modules/spawn-wrap": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", - "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", + "node_modules/node-preload": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", + "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", "dev": true, + "license": "MIT", "dependencies": { - "foreground-child": "^2.0.0", - "is-windows": "^1.0.2", - "make-dir": "^3.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "which": "^2.0.1" + "process-on-spawn": "^1.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/spawn-wrap/node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "node_modules/node-releases": { + "version": "2.0.49", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.49.tgz", + "integrity": "sha512-f06bl1D+8ZDkn2oOQQKAh5/otFWqVnM1Q5oerA8Pex7UfT66Tx4IPHIqVVFKqFT3FUtaDstdgkM7yT7JWhqxfw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=18" } }, - "node_modules/spawn-wrap/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, - "node_modules/spawnd": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/spawnd/-/spawnd-6.2.0.tgz", - "integrity": "sha512-qX/I4lQy4KgVEcNle0kuc4FxFWHISzBhZW1YemPfwmrmQjyZmfTK/OhBKkhrD2ooAaFZEm1maEBLE6/6enwt+g==", + "node_modules/normalize-package-data/node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", "dev": true, + "license": "MIT", "dependencies": { - "exit": "^0.1.2", - "signal-exit": "^3.0.7", - "tree-kill": "^1.2.2" - } - }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "license": "ISC", + "bin": { + "semver": "bin/semver" } }, - "node_modules/spdx-license-ids": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", - "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", - "dev": true - }, - "node_modules/split": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "integrity": "sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==", + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, - "dependencies": { - "through": "2" - }, + "license": "MIT", "engines": { - "node": "*" + "node": ">=0.10.0" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "node_modules/stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "license": "MIT", "dependencies": { - "escape-string-regexp": "^2.0.0" + "path-key": "^3.0.0" }, - "engines": { - "node": ">=10" - } - }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "engines": { "node": ">=8" } }, - "node_modules/start-server-and-test": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/start-server-and-test/-/start-server-and-test-2.0.0.tgz", - "integrity": "sha512-UqKLw0mJbfrsG1jcRLTUlvuRi9sjNuUiDOLI42r7R5fA9dsFoywAy9DoLXNYys9B886E4RCKb+qM1Gzu96h7DQ==", + "node_modules/nyc": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", + "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", "dev": true, + "license": "ISC", "dependencies": { - "arg": "^5.0.2", - "bluebird": "3.7.2", - "check-more-types": "2.24.0", - "debug": "4.3.4", - "execa": "5.1.1", - "lazy-ass": "1.6.0", - "ps-tree": "1.2.0", - "wait-on": "7.0.1" + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "caching-transform": "^4.0.0", + "convert-source-map": "^1.7.0", + "decamelize": "^1.2.0", + "find-cache-dir": "^3.2.0", + "find-up": "^4.1.0", + "foreground-child": "^2.0.0", + "get-package-type": "^0.1.0", + "glob": "^7.1.6", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-hook": "^3.0.0", + "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-processinfo": "^2.0.2", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.2", + "make-dir": "^3.0.0", + "node-preload": "^0.2.1", + "p-map": "^3.0.0", + "process-on-spawn": "^1.0.0", + "resolve-from": "^5.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "spawn-wrap": "^2.0.0", + "test-exclude": "^6.0.0", + "yargs": "^15.0.2" }, "bin": { - "server-test": "src/bin/start.js", - "start-server-and-test": "src/bin/start.js", - "start-test": "src/bin/start.js" + "nyc": "bin/nyc.js" }, "engines": { - "node": ">=6" - } - }, - "node_modules/start-server-and-test/node_modules/axios": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", - "dev": true, - "dependencies": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" + "node": ">=8.9" } }, - "node_modules/start-server-and-test/node_modules/wait-on": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-7.0.1.tgz", - "integrity": "sha512-9AnJE9qTjRQOlTZIldAaf/da2eW0eSRSgcqq85mXQja/DW3MriHxkpODDSUEg+Gri/rKEcXUZHe+cevvYItaog==", + "node_modules/nyc/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, + "license": "MIT", "dependencies": { - "axios": "^0.27.2", - "joi": "^17.7.0", - "lodash": "^4.17.21", - "minimist": "^1.2.7", - "rxjs": "^7.8.0" - }, - "bin": { - "wait-on": "bin/wait-on" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", - "dependencies": { - "internal-slot": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/stream-combiner": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==", + "node_modules/nyc/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "dev": true, + "license": "ISC", "dependencies": { - "duplexer": "~0.1.1" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" } }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "node_modules/nyc/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-hash": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", - "integrity": "sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==", - "dev": true + "license": "MIT" }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/nyc/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/string.prototype.matchall": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", - "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", + "node_modules/nyc/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, + "license": "ISC", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "regexp.prototype.flags": "^1.4.3", - "side-channel": "^1.0.4" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "node_modules/nyc/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "p-locate": "^4.1.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "node_modules/nyc/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, + "license": "ISC", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "brace-expansion": "^1.1.7" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "*" } }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "node_modules/nyc/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/nyc/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "p-limit": "^2.2.0" }, "engines": { "node": ">=8" } }, - "node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "node_modules/nyc/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "node_modules/nyc/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "node_modules/nyc/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/nyc/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "license": "MIT", "dependencies": { - "min-indent": "^1.0.0" + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" }, "engines": { "node": ">=8" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "node_modules/nyc/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "dev": true, - "engines": { - "node": ">=8" + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=6" } }, - "node_modules/stylis": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", - "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/object-deep-merge": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/object-deep-merge/-/object-deep-merge-1.0.5.tgz", + "integrity": "sha512-3DioFgOzetbxbeUq8pB2NunXo8V0n4EvqsWM/cJoI6IA9zghd7cl/2pBOuWRf4dlvA+fcg5ugFMZaN2/RuoaGg==", + "dev": true, + "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" + "type-fest": "4.2.0" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "node_modules/object-deep-merge/node_modules/type-fest": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.2.0.tgz", + "integrity": "sha512-5zknd7Dss75pMSED270A1RQS3KloqRJA9XbXLe0eCxyw7xXFb3rd+9B0UQ/0E+LQT6lnrLviEolYORlRWamn4w==", "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -11883,2313 +13842,5857 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/sxh": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/sxh/-/sxh-1.0.0.tgz", - "integrity": "sha512-mfkOqpA7uR/p72kdeRJArJmi9wDJBbD8GumWwtdsOZKmUoHqgDdnMs6T5G8YcxczkwW3sQfA6s4VazmPF6tA5g==", - "dev": true - }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true - }, - "node_modules/tabster": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/tabster/-/tabster-4.4.1.tgz", - "integrity": "sha512-Am5XszZz/5PnWVWveQubi4jfE6aJzTAEJ+c9Bc6R0tTEl1XYaPZpFrJUFb/SCq0BPE6ncFxLyPPpy6CwrIhnVg==", + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "license": "MIT", "dependencies": { - "keyborg": "^2.0.0", - "tslib": "^2.3.1" - } - }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "peer": true, + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, "engines": { - "node": ">=6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", - "dev": true, - "dependencies": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" } }, - "node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "dev": true, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "license": "MIT", "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" }, "engines": { - "node": ">=6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/terser": { - "version": "5.17.4", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.17.4.tgz", - "integrity": "sha512-jcEKZw6UPrgugz/0Tuk/PVyLAPfMBJf5clnGueo45wTweoV8yh7Q7PEkhkJ5uuUbC7zAxEcG3tqNr1bstkQ8nw==", + "node_modules/object.entries": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" }, "engines": { - "node": ">=10" + "node": ">= 0.4" } }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.9", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", - "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.8" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">= 10.13.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz", - "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==", + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">= 10.13.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/terser-webpack-plugin/node_modules/serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, - "peer": true, + "license": "ISC", "dependencies": { - "randombytes": "^2.1.0" + "wrappy": "1" } }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, - "peer": true - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, + "license": "MIT", "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" + "mimic-fn": "^2.1.0" }, "engines": { - "node": ">=8" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, + "node_modules/opossum": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/opossum/-/opossum-8.5.0.tgz", + "integrity": "sha512-LZNvs+p9/ZbG4oN6unnjh4hTxkB0dyHKI2p7azVt8w+//GKDpfHss6WR7KebbpzGEssYwtSd8Mvwxqcmxg10NA==", + "license": "Apache-2.0", "engines": { - "node": ">=4" + "node": "^24 || ^22 || ^21 || ^20 || ^18 || ^16" } }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", "dependencies": { - "is-number": "^7.0.0" + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" }, "engines": { - "node": ">=8.0" + "node": ">= 0.8.0" } }, - "node_modules/tough-cookie": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", - "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", + "node_modules/os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==", "dev": true, - "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - }, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/tr46": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", - "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", "dev": true, + "license": "MIT", "dependencies": { - "punycode": "^2.3.0" + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" }, "engines": { - "node": ">=14" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, - "bin": { - "tree-kill": "cli.js" + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ts-mocha": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/ts-mocha/-/ts-mocha-10.0.0.tgz", - "integrity": "sha512-VRfgDO+iiuJFlNB18tzOfypJ21xn2xbuZyDvJvqpTbWgkAgD17ONGr8t+Tl8rcBtOBdjXp5e/Rk+d39f7XBHRw==", + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, + "license": "MIT", "dependencies": { - "ts-node": "7.0.1" - }, - "bin": { - "ts-mocha": "bin/ts-mocha" + "p-limit": "^3.0.2" }, "engines": { - "node": ">= 6.X.X" - }, - "optionalDependencies": { - "tsconfig-paths": "^3.5.0" + "node": ">=10" }, - "peerDependencies": { - "mocha": "^3.X.X || ^4.X.X || ^5.X.X || ^6.X.X || ^7.X.X || ^8.X.X || ^9.X.X || ^10.X.X" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ts-node": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", - "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", + "node_modules/p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", "dev": true, + "license": "MIT", "dependencies": { - "arrify": "^1.0.0", - "buffer-from": "^1.1.0", - "diff": "^3.1.0", - "make-error": "^1.1.1", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", - "source-map-support": "^0.5.6", - "yn": "^2.0.0" - }, - "bin": { - "ts-node": "dist/bin.js" + "aggregate-error": "^3.0.0" }, "engines": { - "node": ">=4.2.0" + "node": ">=8" } }, - "node_modules/ts-node/node_modules/diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.3.1" + "node": ">=6" } }, - "node_modules/tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "node_modules/pac-proxy-agent": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz", + "integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==", "dev": true, - "optional": true, + "license": "MIT", "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" + "@tootallnate/quickjs-emscripten": "^0.23.0", + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "get-uri": "^6.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.6", + "pac-resolver": "^7.0.1", + "socks-proxy-agent": "^8.0.5" + }, + "engines": { + "node": ">= 14" } }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "node_modules/pac-proxy-agent/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", "dev": true, - "optional": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-proxy-agent/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", "dependencies": { - "minimist": "^1.2.0" + "agent-base": "^7.1.2", + "debug": "4" }, - "bin": { - "json5": "lib/cli.js" + "engines": { + "node": ">= 14" } }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "node_modules/pac-resolver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", + "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", "dev": true, - "optional": true, + "license": "MIT", + "dependencies": { + "degenerator": "^5.0.0", + "netmask": "^2.0.2" + }, "engines": { - "node": ">=4" + "node": ">= 14" } }, - "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "node_modules/package-hash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", + "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", "dev": true, + "license": "ISC", "dependencies": { - "tslib": "^1.8.1" + "graceful-fs": "^4.1.15", + "hasha": "^5.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" }, "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + "node": ">=8" } }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, + "license": "MIT", "dependencies": { - "prelude-ls": "^1.2.1" + "callsites": "^3.0.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=6" } }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "node_modules/parse-imports-exports": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/parse-imports-exports/-/parse-imports-exports-0.2.4.tgz", + "integrity": "sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ==", "dev": true, - "engines": { - "node": ">=4" + "license": "MIT", + "dependencies": { + "parse-statements": "1.0.11" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "license": "MIT", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "node_modules/parse-statements": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/parse-statements/-/parse-statements-1.0.11.tgz", + "integrity": "sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==", "dev": true, - "dependencies": { - "is-typedarray": "^1.0.0" + "license": "MIT" + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "license": "MIT" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" } }, - "node_modules/typedoc": { - "version": "0.24.7", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.24.7.tgz", - "integrity": "sha512-zzfKDFIZADA+XRIp2rMzLe9xZ6pt12yQOhCr7cD7/PBTjhPmMyMvGrkZ2lPNJitg3Hj1SeiYFNzCsSDrlpxpKw==", + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, - "dependencies": { - "lunr": "^2.3.9", - "marked": "^4.3.0", - "minimatch": "^9.0.0", - "shiki": "^0.14.1" - }, - "bin": { - "typedoc": "bin/typedoc" - }, + "license": "MIT", "engines": { - "node": ">= 14.14" - }, - "peerDependencies": { - "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x" + "node": ">=0.10.0" } }, - "node_modules/typedoc/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" + "license": "MIT", + "engines": { + "node": ">=8" } }, - "node_modules/typedoc/node_modules/minimatch": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.0.tgz", - "integrity": "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==", + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^2.0.1" + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/typescript": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", - "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/path-scurry/node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==", + "dev": true, + "license": [ + "MIT", + "Apache2" + ], + "dependencies": { + "through": "~2.3" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkcs7": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/pkcs7/-/pkcs7-1.0.4.tgz", + "integrity": "sha512-afRERtHn54AlwaF2/+LFszyAANTCggGilmcmILUzEjvs3XgFZT+xE6+QWQcAGmu4xajy+Xtj7acLOPdx5/eXWQ==", + "license": "Apache-2.0", + "dependencies": { + "@babel/runtime": "^7.5.5" + }, "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "pkcs7": "bin/cli.js" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" }, "engines": { - "node": ">=12.20" + "node": ">=8" } }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=8" } }, - "node_modules/unbzip2-stream": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", - "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "license": "MIT", "dependencies": { - "buffer": "^5.2.1", - "through": "^2.3.8" + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/unbzip2-stream/node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "license": "MIT", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 4.0.0" + "node": ">=4" } }, - "node_modules/update-browserslist-db": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", "dev": true, "funding": [ { "type": "opencollective", - "url": "https://opencollective.com/browserslist" + "url": "https://opencollective.com/postcss/" }, { "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" + "url": "https://tidelift.com/funding/github/npm/postcss" }, { "type": "github", "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "nanoid": "^3.3.12", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.8.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.4.tgz", + "integrity": "sha512-N2MylSdi48+5N/6S5j+maeHbUSIzzZ5uOcX5Hm4QpV8Dkb1HFjfAKTKX6yNPJQD9AhcT3ifHNB66tWTTJDi11Q==", + "dev": true, + "license": "MIT", "bin": { - "update-browserslist-db": "cli.js" + "prettier": "bin/prettier.cjs" }, - "peerDependencies": { - "browserslist": ">= 4.21.0" + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "node_modules/prettier-linter-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz", + "integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==", "dev": true, + "license": "MIT", "dependencies": { - "punycode": "^2.1.0" + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" } }, - "node_modules/url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==", + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "license": "MIT", "dependencies": { - "punycode": "1.3.2", - "querystring": "0.2.0" + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/url/node_modules/punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==" - }, - "node_modules/url/node_modules/querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", - "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "node_modules/printj": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", + "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==", + "license": "Apache-2.0", + "bin": { + "printj": "bin/printj.njs" + }, "engines": { - "node": ">=0.4.x" + "node": ">=0.8" } }, - "node_modules/use-disposable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/use-disposable/-/use-disposable-1.0.1.tgz", - "integrity": "sha512-5Sle1XEmK3lw3xyGqeIY7UKkiUgF+TxwUty7fTsqM5D5AxfQfo2ft+LY9xKCA+W5YbaBFbOkWfQsZY/y5JhInA==", - "peerDependencies": { - "@types/react": ">=16.8.0 <19.0.0", - "@types/react-dom": ">=16.8.0 <19.0.0", - "react": ">=16.8.0 <19.0.0", - "react-dom": ">=16.8.0 <19.0.0" + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" } }, - "node_modules/use-resize-observer": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/use-resize-observer/-/use-resize-observer-9.1.0.tgz", - "integrity": "sha512-R25VqO9Wb3asSD4eqtcxk8sJalvIOYBqS8MNZlpDSQ4l4xMQxC/J7Id9HoTqPq8FwULIn0PVW+OAqF2dyYbjow==", + "node_modules/process-on-spawn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.1.0.tgz", + "integrity": "sha512-JOnOPQ/8TZgjs1JIH/m9ni7FfimjNa/PRx7y/Wb5qdItsnhO0jE4AT7fC0HjC28DUQWDr50dwSYZLdRMlqDq3Q==", + "dev": true, + "license": "MIT", "dependencies": { - "@juggle/resize-observer": "^3.3.1" + "fromentries": "^1.2.0" }, - "peerDependencies": { - "react": "16.8.0 - 18", - "react-dom": "16.8.0 - 18" + "engines": { + "node": ">=8" } }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } }, - "node_modules/uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", - "bin": { - "uuid": "dist/bin/uuid" + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" } }, - "node_modules/vite": { - "version": "4.4.9", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.9.tgz", - "integrity": "sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==", + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/proxy-agent": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz", + "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==", "dev": true, + "license": "MIT", "dependencies": { - "esbuild": "^0.18.10", - "postcss": "^8.4.27", - "rollup": "^3.27.1" - }, - "bin": { - "vite": "bin/vite.js" + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.6", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.1.0", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.5" }, "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - }, - "peerDependencies": { - "@types/node": ">= 14", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } + "node": ">= 14" } }, - "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", - "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", - "cpu": [ - "arm" - ], + "node_modules/proxy-agent/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", "dev": true, - "optional": true, - "os": [ - "android" - ], + "license": "MIT", "engines": { - "node": ">=12" + "node": ">= 14" } }, - "node_modules/vite/node_modules/@esbuild/android-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", - "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", - "cpu": [ - "arm64" - ], + "node_modules/proxy-agent/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "dev": true, - "optional": true, - "os": [ - "android" - ], + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, "engines": { - "node": ">=12" + "node": ">= 14" } }, - "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", - "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", - "cpu": [ - "x64" - ], + "node_modules/proxy-agent/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "dev": true, - "optional": true, - "os": [ - "android" - ], + "license": "ISC", "engines": { "node": ">=12" } }, - "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", - "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", - "cpu": [ - "arm64" - ], + "node_modules/proxy-agent/node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true, - "optional": true, - "os": [ - "darwin" - ], + "license": "MIT" + }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=10" } }, - "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", - "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", - "cpu": [ - "x64" - ], + "node_modules/ps-tree": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", + "integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==", "dev": true, - "optional": true, - "os": [ - "darwin" - ], + "license": "MIT", + "dependencies": { + "event-stream": "=3.3.4" + }, + "bin": { + "ps-tree": "bin/ps-tree.js" + }, "engines": { - "node": ">=12" + "node": ">= 0.10" } }, - "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", - "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", - "cpu": [ - "arm64" - ], + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", "dev": true, - "optional": true, - "os": [ - "freebsd" - ], + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=6" } }, - "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", - "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", - "cpu": [ - "x64" - ], + "node_modules/puppeteer": { + "version": "24.43.1", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.43.1.tgz", + "integrity": "sha512-/FSOViCrqRdb1HDocpsM9Z1giA71gTQPUt3SpHGVRALKAy/rJr1fLFYZW9F23qPxqVxTHQnbh/5B5opJST3kAw==", "dev": true, - "optional": true, - "os": [ - "freebsd" - ], + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@puppeteer/browsers": "2.13.2", + "chromium-bidi": "14.0.0", + "cosmiconfig": "^9.0.0", + "devtools-protocol": "0.0.1608973", + "puppeteer-core": "24.43.1", + "typed-query-selector": "^2.12.2" + }, + "bin": { + "puppeteer": "lib/cjs/puppeteer/node/cli.js" + }, "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", - "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", - "cpu": [ - "arm" - ], + "node_modules/puppeteer-core": { + "version": "24.43.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.43.1.tgz", + "integrity": "sha512-T5ScUMAsmhdNbgDR41AGESYeS6V9MSgetkSnVhhW+gXvzC42VesKCn5ld87gAZDJ6vLHL9GkRvY9WtQWSnwFbw==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "license": "Apache-2.0", + "dependencies": { + "@puppeteer/browsers": "2.13.2", + "chromium-bidi": "14.0.0", + "debug": "^4.4.3", + "devtools-protocol": "0.0.1608973", + "typed-query-selector": "^2.12.2", + "webdriver-bidi-protocol": "0.4.1", + "ws": "^8.20.0" + }, "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", - "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", - "cpu": [ - "arm64" - ], + "node_modules/puppeteer-core/node_modules/ws": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/puppeteer/node_modules/cosmiconfig": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.2.tgz", + "integrity": "sha512-gtTZxTDau1wL7Y7zifc2dd8jHSK/k6BTx/2Xp/BpdlAdnlYWFVt7qhJqgwi7637yRwRQ3qL4ZidbB4I8tA5VOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/qs": { + "version": "6.15.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.3.tgz", + "integrity": "sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==", + "license": "BSD-3-Clause", + "dependencies": { + "es-define-property": "^1.0.1", + "side-channel": "^1.1.1" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-babylonjs": { + "version": "3.1.27", + "resolved": "https://registry.npmjs.org/react-babylonjs/-/react-babylonjs-3.1.27.tgz", + "integrity": "sha512-eh5nOKoiwINUpS0vBRKYs+fGcK9ckBgB5VVml7mFvUv+nAu5znwpFE8knx0AiihA4UyoZnldYOjlOsgaHZwitw==", + "license": "MIT", + "dependencies": { + "react-reconciler": "^0.27.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "@babylonjs/core": "5.x || 6.x", + "@babylonjs/gui": "5.x || 6.x", + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-colorful": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.7.0.tgz", + "integrity": "sha512-fuesYIemttah97XmsIHmz4OORDHiSFzyc9HMAIrCHJou2jaRQmL8cFJ76K4zQhhj8jzwOBlOi4BaGTjjOZCfTg==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-dom/node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "license": "MIT" + }, + "node_modules/react-is-18": { + "name": "react-is", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT" + }, + "node_modules/react-is-19": { + "name": "react-is", + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.7.tgz", + "integrity": "sha512-kZFnouyVv7eP/Phmrlo9FK+zcAdriZJvzxXHF1Sl1P377WSGe2G/JxVolhTrB/jeV47lKImhNUsijjHAAbcl/A==", + "license": "MIT" + }, + "node_modules/react-media-template-ts": { + "resolved": "samples/typescript/21.react-media-template", + "link": true + }, + "node_modules/react-reconciler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.27.0.tgz", + "integrity": "sha512-HmMDKciQjYmBRGuuhIaKA1ba/7a+UsM5FzOZsMO2JYHt9Jh8reCb7j1eDC95NOyUlKM9KRyvdx0flBuDvYSBoA==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.21.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, + "node_modules/react-reconciler/node_modules/scheduler": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.21.0.tgz", + "integrity": "sha512-1r87x5fz9MXqswA2ERLo0EbOAU74DpIUO090gIasYTqlVoJeMcl+Z1Rg7WHz+qtPujhS/hGIt9kxZOYBV3faRQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/react-refresh": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", + "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-router": { + "version": "6.30.4", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.4.tgz", + "integrity": "sha512-SVUsDe+DybHM/WmYKIVYhZh1o5Dcuf16yM6WjG02Q9XVFMZIJyHYhwrr6bFBXZkVP6z69kNkMyBCujt8FaFLJA==", + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.23.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.30.4", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.4.tgz", + "integrity": "sha512-q4HvNl+mmDdkS0g+MqiBZNteQJCuimWoOyHMy4T/RQLAn9Z29+E91QXRaxOujeMl2HTzRSS0KFPd7lxX3PjV0Q==", + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.23.3", + "react-router": "6.30.4" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/react-video": { + "resolved": "samples/javascript/02.react-video", + "link": true + }, + "node_modules/react-video-js": { + "resolved": "samples/typescript/11.react-video-js", + "link": true + }, + "node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/readdirp/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/readline-sync": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.10.tgz", + "integrity": "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==", + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "license": "MIT", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "license": "MIT", + "dependencies": { + "redis-errors": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp-tree": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz", + "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==", + "dev": true, + "license": "MIT", + "bin": { + "regexp-tree": "bin/regexp-tree" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regjsparser": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.10.0.tgz", + "integrity": "sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/release-zalgo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", + "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==", + "dev": true, + "license": "ISC", + "dependencies": { + "es6-error": "^4.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true, + "license": "ISC" + }, + "node_modules/resolve": { + "version": "2.0.0-next.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz", + "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.2", + "node-exports-info": "^1.6.0", + "object-keys": "^1.1.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-dir": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", + "integrity": "sha512-QxMPqI6le2u0dCLyiGzgy92kjkkL6zO0XyvHzjdTNH3zM6e5Hz3BwG6+aEyNgiQ5Xz6PwTwgQEj3U50dByPKIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "expand-tilde": "^1.2.2", + "global-modules": "^0.2.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/rollup": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.2.tgz", + "integrity": "sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.62.2", + "@rollup/rollup-android-arm64": "4.62.2", + "@rollup/rollup-darwin-arm64": "4.62.2", + "@rollup/rollup-darwin-x64": "4.62.2", + "@rollup/rollup-freebsd-arm64": "4.62.2", + "@rollup/rollup-freebsd-x64": "4.62.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.2", + "@rollup/rollup-linux-arm-musleabihf": "4.62.2", + "@rollup/rollup-linux-arm64-gnu": "4.62.2", + "@rollup/rollup-linux-arm64-musl": "4.62.2", + "@rollup/rollup-linux-loong64-gnu": "4.62.2", + "@rollup/rollup-linux-loong64-musl": "4.62.2", + "@rollup/rollup-linux-ppc64-gnu": "4.62.2", + "@rollup/rollup-linux-ppc64-musl": "4.62.2", + "@rollup/rollup-linux-riscv64-gnu": "4.62.2", + "@rollup/rollup-linux-riscv64-musl": "4.62.2", + "@rollup/rollup-linux-s390x-gnu": "4.62.2", + "@rollup/rollup-linux-x64-gnu": "4.62.2", + "@rollup/rollup-linux-x64-musl": "4.62.2", + "@rollup/rollup-openbsd-x64": "4.62.2", + "@rollup/rollup-openharmony-arm64": "4.62.2", + "@rollup/rollup-win32-arm64-msvc": "4.62.2", + "@rollup/rollup-win32-ia32-msvc": "4.62.2", + "@rollup/rollup-win32-x64-gnu": "4.62.2", + "@rollup/rollup-win32-x64-msvc": "4.62.2", + "fsevents": "~2.3.2" + } + }, + "node_modules/rtl-css-js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.1.tgz", + "integrity": "sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.1.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.4.tgz", + "integrity": "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT", + "peer": true + }, + "node_modules/schema-utils": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", + "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/schema-utils/node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/schema-utils/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/schema-utils/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/secure-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/secure-keys/-/secure-keys-1.0.0.tgz", + "integrity": "sha512-nZi59hW3Sl5P3+wOO89eHBAAGwmCPd2aE1+dLZV5MO+ItQctIvAqihzaAXIQhvtH4KJPxM080HsnqltR2y8cWg==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-ts": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/semver-ts/-/semver-ts-1.0.3.tgz", + "integrity": "sha512-RMf2+Nbd0Hiq5u8LADzqnSRb09Vu1UKOLFw9P9nm8XY3JPeFjv3DLVYBZjPWFHUxBVz7ktIVGR3xFjYilHlXng==", + "license": "ISC", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/serialize-error": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-8.1.0.tgz", + "integrity": "sha512-3NnuWfM6vBYoy5gZFvHiYsVbafvI9vZv/+jlIigFn4oP4zjNPK3LhcY0xSCgeb1a5L8jO71Mit9LlNoi2UfDDQ==", + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true, + "license": "ISC" + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/sha.js": { + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", + "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", + "license": "(MIT AND BSD-3-Clause)", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.0" + }, + "bin": { + "sha.js": "bin.js" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/sillyname": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/sillyname/-/sillyname-0.1.0.tgz", + "integrity": "sha512-GWA0Zont13ov+cMNw4T7nU4SCyW8jdhD3vjA5+qs8jr+09sCPxOf+FPS5zE0c9pYlCwD+NU/CiMimY462lgG9g==", + "license": "MIT" + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socket.io-client": { + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.3.tgz", + "integrity": "sha512-uP0bpjWrjQmUt5DTHq9RuoCBdFJF10cdX9X+a368j/Ft0wmaVgxlrjvK3kjvgCODOMMOz9lcaRzxmso0bTWZ/g==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.4.1", + "engine.io-client": "~6.6.1", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.6.tgz", + "integrity": "sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.4.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.9.tgz", + "integrity": "sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw==", + "dev": true, + "license": "MIT", + "dependencies": { + "ip-address": "^10.1.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/socks-proxy-agent/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/spawn-wrap": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", + "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^2.0.0", + "is-windows": "^1.0.2", + "make-dir": "^3.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "which": "^2.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/spawn-wrap/node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spawnd": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/spawnd/-/spawnd-11.0.0.tgz", + "integrity": "sha512-brBHv9HYi8lwNvbI7X52NDZe4yAdsQwvr81b/r98LaN82LzeEnQ0L6YXBvG25zhgWRadTwB+4GsUu9NrNQcVzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "signal-exit": "^4.1.0", + "tree-kill": "^1.2.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/spawnd/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-correct/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", + "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", + "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/split": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "through": "2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "license": "BSD-3-Clause" + }, + "node_modules/stable-hash-x": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/stable-hash-x/-/stable-hash-x-0.2.0.tgz", + "integrity": "sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/standard-as-callback": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", + "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==", + "license": "MIT" + }, + "node_modules/start-server-and-test": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/start-server-and-test/-/start-server-and-test-2.1.5.tgz", + "integrity": "sha512-A/SbXpgXE25ScSkpLLqvGvVZT0ykN6+AzS8tVqMBCTxbJy2Nwuen59opT+afalK5aS+AuQmZs0EsLwjnuDN+/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "arg": "^5.0.2", + "bluebird": "3.7.2", + "check-more-types": "2.24.0", + "debug": "4.4.3", + "execa": "5.1.1", + "lazy-ass": "1.6.0", + "ps-tree": "1.2.0", + "wait-on": "9.0.4" + }, + "bin": { + "server-test": "src/bin/start.js", + "start-server-and-test": "src/bin/start.js", + "start-test": "src/bin/start.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/start-server-and-test/node_modules/wait-on": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-9.0.4.tgz", + "integrity": "sha512-k8qrgfwrPVJXTeFY8tl6BxVHiclK11u72DVKhpybHfUL/K6KM4bdyK9EhIVYGytB5MJe/3lq4Tf0hrjM+pvJZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "axios": "^1.13.5", + "joi": "^18.0.2", + "lodash": "^4.17.23", + "minimist": "^1.2.8", + "rxjs": "^7.8.2" + }, + "bin": { + "wait-on": "bin/wait-on" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "duplexer": "~0.1.1" + } + }, + "node_modules/streamx": { + "version": "2.28.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.28.0.tgz", + "integrity": "sha512-1Yowhzjf0ivGMrTIkY9hav5TxobO9qIVqUE41fiCGMGgc3CLlf4MY+9AHmZqBWgDTue0fY9zWjYFVyf6Diuobw==", + "dev": true, + "license": "MIT", + "dependencies": { + "events-universal": "^1.0.0", + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" + } + }, + "node_modules/string-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", + "integrity": "sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==", + "license": "CC0-1.0" + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.11.tgz", + "integrity": "sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-object-atoms": "^1.1.2", + "has-property-descriptors": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.10.tgz", + "integrity": "sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stylis": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.4.0.tgz", + "integrity": "sha512-5Z9ZpRzfuH6l/UAvCPAPUo3665Nk2wLaZU3x+TLHKVzIz33+sbJqbtrYoC3KD4/uVOr2Zp+L0LySezP9OHV9yA==", + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/synckit": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.13.tgz", + "integrity": "sha512-eNRKgb3z66Yp3D2CixVujOUvXLFUTij/zVnV8KRyvFdQwpz7I5DS8UfRkTeLzb64u+dkzDSdelE24izu+zSSUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.3.6" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, + "node_modules/tabster": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/tabster/-/tabster-8.8.0.tgz", + "integrity": "sha512-eGFXgtvKOQP5BywDI9Ngs+Atm6TRj45epAAqWKyVoi+HmOmdamEB//1H/FttLdNly/+Cz+GJ4RN8TnXTw0KwfA==", + "license": "MIT", + "dependencies": { + "keyborg": "^2.14.0", + "tslib": "^2.8.1" + } + }, + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/tar-fs": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.2.tgz", + "integrity": "sha512-QGxxTxxyleAdyM3kpFs14ymbYmNFrfY+pHj7Z8FgtbZ7w2//VAgLMac7sT6nRpIHjppXO2AwwEOg0bPFVRcmXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0", + "tar-stream": "^3.1.5" + }, + "optionalDependencies": { + "bare-fs": "^4.0.1", + "bare-path": "^3.0.0" + } + }, + "node_modules/tar-stream": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.2.0.tgz", + "integrity": "sha512-ojzvCvVaNp6aOTFmG7jaRD0meowIAuPc3cMMhSgKiVWws1GyHbGd/xvnyuRKcKlMpt3qvxx6r0hreCNITP9hIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "b4a": "^1.6.4", + "bare-fs": "^4.5.5", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "node_modules/tar-stream/node_modules/b4a": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.1.tgz", + "integrity": "sha512-aiqre1Nr0B/6DgE2N5vwTc+2/oQZ4Wh1t4NznYY4E00y8LCt6NqdRv81so00oo27D8MVKTpUa/MwUUtBLXCoDw==", + "dev": true, + "license": "Apache-2.0", + "peerDependencies": { + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true + } + } + }, + "node_modules/teex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", + "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "streamx": "^2.12.5" + } + }, + "node_modules/terser": { + "version": "5.48.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.48.0.tgz", + "integrity": "sha512-J/9An6vs9Us6wKRriSFXBWdRZapREHqFzdNUKk0pmu804EMR6dr6winwo7e5JDxN4xahxQsuysyYFwlwj4XN/Q==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.6.1.tgz", + "integrity": "sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "terser": "^5.31.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@minify-html/node": { + "optional": true + }, + "@swc/core": { + "optional": true + }, + "@swc/css": { + "optional": true + }, + "@swc/html": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "cssnano": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "html-minifier-terser": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "postcss": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/text-decoder": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.7.tgz", + "integrity": "sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" + } + }, + "node_modules/text-decoder/node_modules/b4a": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.1.tgz", + "integrity": "sha512-aiqre1Nr0B/6DgE2N5vwTc+2/oQZ4Wh1t4NznYY4E00y8LCt6NqdRv81so00oo27D8MVKTpUa/MwUUtBLXCoDw==", + "dev": true, + "license": "Apache-2.0", + "peerDependencies": { + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true + } + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tmp": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", + "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, + "node_modules/to-buffer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz", + "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==", + "license": "MIT", + "dependencies": { + "isarray": "^2.0.5", + "safe-buffer": "^5.2.1", + "typed-array-buffer": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-api-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", + "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-mocha": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/ts-mocha/-/ts-mocha-10.1.0.tgz", + "integrity": "sha512-T0C0Xm3/WqCuF2tpa0GNGESTBoKZaiqdUP8guNv4ZY316AFXlyidnrzQ1LUrCT0Wb1i3J0zFTgOh/55Un44WdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ts-node": "7.0.1" + }, + "bin": { + "ts-mocha": "bin/ts-mocha" + }, + "engines": { + "node": ">= 6.X.X" + }, + "optionalDependencies": { + "tsconfig-paths": "^3.5.0" + }, + "peerDependencies": { + "mocha": "^3.X.X || ^4.X.X || ^5.X.X || ^6.X.X || ^7.X.X || ^8.X.X || ^9.X.X || ^10.X.X || ^11.X.X" + } + }, + "node_modules/ts-morph": { + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-22.0.0.tgz", + "integrity": "sha512-M9MqFGZREyeb5fTl6gNHKZLqBQA0TjA1lea+CR48R8EBTDuWrNqW6ccC5QvjNR4s6wDumD3LTCjOFSp9iwlzaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ts-morph/common": "~0.23.0", + "code-block-writer": "^13.0.1" + } + }, + "node_modules/ts-node": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", + "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "arrify": "^1.0.0", + "buffer-from": "^1.1.0", + "diff": "^3.1.0", + "make-error": "^1.1.1", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "source-map-support": "^0.5.6", + "yn": "^2.0.0" + }, + "bin": { + "ts-node": "dist/bin.js" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/ts-node/node_modules/diff": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.1.tgz", + "integrity": "sha512-Z3u54A8qGyqFOSr2pk0ijYs8mOE9Qz8kTvtKeBI+upoG9j04Sq+oI7W8zAJiQybDcESET8/uIdHzs0p3k4fZlw==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.8.tgz", + "integrity": "sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "for-each": "^0.3.5", + "gopd": "^1.2.0", + "is-typed-array": "^1.1.15", + "possible-typed-array-names": "^1.1.0", + "reflect.getprototypeof": "^1.0.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-query-selector": { + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.2.tgz", + "integrity": "sha512-EOPFbyIub4ngnEdqi2yOcNeDLaX/0jcE1JoAXQDDMIthap7FoN795lc/SHfIq2d416VufXpM8z/lD+WRm2gfOQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typescript": { + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici-types": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz", + "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==", + "license": "MIT" + }, + "node_modules/unrs-resolver": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.12.2.tgz", + "integrity": "sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.4" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.12.2", + "@unrs/resolver-binding-android-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-x64": "1.12.2", + "@unrs/resolver-binding-freebsd-x64": "1.12.2", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-arm64-musl": "1.12.2", + "@unrs/resolver-binding-linux-loong64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-loong64-musl": "1.12.2", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-musl": "1.12.2", + "@unrs/resolver-binding-linux-s390x-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-musl": "1.12.2", + "@unrs/resolver-binding-openharmony-arm64": "1.12.2", + "@unrs/resolver-binding-wasm32-wasi": "1.12.2", + "@unrs/resolver-binding-win32-arm64-msvc": "1.12.2", + "@unrs/resolver-binding-win32-ia32-msvc": "1.12.2", + "@unrs/resolver-binding-win32-x64-msvc": "1.12.2" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz", + "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==", + "license": "MIT", + "dependencies": { + "punycode": "^1.4.1", + "qs": "^6.12.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "license": "MIT" + }, + "node_modules/use-resize-observer": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/use-resize-observer/-/use-resize-observer-9.1.0.tgz", + "integrity": "sha512-R25VqO9Wb3asSD4eqtcxk8sJalvIOYBqS8MNZlpDSQ4l4xMQxC/J7Id9HoTqPq8FwULIn0PVW+OAqF2dyYbjow==", + "license": "MIT", + "dependencies": { + "@juggle/resize-observer": "^3.3.1" + }, + "peerDependencies": { + "react": "16.8.0 - 18", + "react-dom": "16.8.0 - 18" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/validate-npm-package-license/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/video.js": { + "version": "8.23.8", + "resolved": "https://registry.npmjs.org/video.js/-/video.js-8.23.8.tgz", + "integrity": "sha512-plZuWxN4clhDESSpi3QLYVs6tgnnf9qT9SA4iahHwZEmdVSuUh4+O6vQPcA5XqiEDvjeBDJvLafH1bhkAXaXKQ==", + "license": "Apache-2.0", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@videojs/http-streaming": "^3.17.4", + "@videojs/vhs-utils": "^4.1.1", + "@videojs/xhr": "2.7.0", + "aes-decrypter": "^4.0.2", + "global": "4.4.0", + "m3u8-parser": "^7.2.0", + "mpd-parser": "^1.3.1", + "mux.js": "^7.0.1", + "videojs-contrib-quality-levels": "4.1.0", + "videojs-font": "4.2.0", + "videojs-vtt.js": "0.15.5" + } + }, + "node_modules/videojs-contrib-quality-levels": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/videojs-contrib-quality-levels/-/videojs-contrib-quality-levels-4.1.0.tgz", + "integrity": "sha512-TfrXJJg1Bv4t6TOCMEVMwF/CoS8iENYsWNKip8zfhB5kTcegiFYezEA0eHAJPU64ZC8NQbxQgOwAsYU8VXbOWA==", + "license": "Apache-2.0", + "dependencies": { + "global": "^4.4.0" + }, + "engines": { + "node": ">=16", + "npm": ">=8" + }, + "peerDependencies": { + "video.js": "^8" + } + }, + "node_modules/videojs-font": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/videojs-font/-/videojs-font-4.2.0.tgz", + "integrity": "sha512-YPq+wiKoGy2/M7ccjmlvwi58z2xsykkkfNMyIg4xb7EZQQNwB71hcSsB3o75CqQV7/y5lXkXhI/rsGAS7jfEmQ==", + "license": "Apache-2.0" + }, + "node_modules/videojs-vtt.js": { + "version": "0.15.5", + "resolved": "https://registry.npmjs.org/videojs-vtt.js/-/videojs-vtt.js-0.15.5.tgz", + "integrity": "sha512-yZbBxvA7QMYn15Lr/ZfhhLPrNpI/RmCSCqgIff57GC2gIrV5YfyzLfLyZMj0NnZSAz8syB4N0nHXpZg9MyrMOQ==", + "license": "Apache-2.0", + "dependencies": { + "global": "^4.3.1" + } + }, + "node_modules/vite": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.3.tgz", + "integrity": "sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/wait-on": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-8.0.5.tgz", + "integrity": "sha512-J3WlS0txVHkhLRb2FsmRg3dkMTCV1+M6Xra3Ho7HzZDHpE7DCOnoSoCJsZotrmW3uRMhvIJGSKUKrh/MeF4iag==", + "dev": true, + "license": "MIT", + "dependencies": { + "axios": "^1.12.1", + "joi": "^18.0.1", + "lodash": "^4.17.21", + "minimist": "^1.2.8", + "rxjs": "^7.8.2" + }, + "bin": { + "wait-on": "bin/wait-on" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/watchpack": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.2.tgz", + "integrity": "sha512-6i/00NBjP4yGPs+caKSyRfpTF/8Torsu0MOW3mMzIbhgISFder8i7xbqgHlLMwJrdiN8ndBV3UA1/AfzPSr+jg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/web-vitals": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-3.5.2.tgz", + "integrity": "sha512-c0rhqNcHXRkY/ogGDJQxZ9Im9D19hDihbzSQJrsioex+KnFgmMzBiy57Z1EjkhX/+OjyBpclDCzz2ITtjokFmg==", + "license": "Apache-2.0" + }, + "node_modules/webdriver-bidi-protocol": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.4.1.tgz", + "integrity": "sha512-ARrjNjtWRRs2w4Tk7nqrf2gBI0QXWuOmMCx2hU+1jUt6d00MjMxURrhxhGbrsoiZKJrhTSTzbIrc554iKI10qw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/webpack": { + "version": "5.107.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.107.2.tgz", + "integrity": "sha512-v7RhXaJbpMlV0D7hC7lb2EbnxkoeUqf9qhKr6lozx3Q48pmFrqqNRmZFUEGmi7pSwm6fCQ2H1IjvCkHqdpVdjQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/estree": "^1.0.8", + "@types/json-schema": "^7.0.15", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.16.0", + "acorn-import-phases": "^1.0.3", + "browserslist": "^4.28.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.22.0", + "es-module-lexer": "^2.1.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "loader-runner": "^4.3.2", + "mime-db": "^1.54.0", + "neo-async": "^2.6.2", + "schema-utils": "^4.3.3", + "tapable": "^2.3.0", + "terser-webpack-plugin": "^5.5.0", + "watchpack": "^2.5.1", + "webpack-sources": "^3.5.0" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-sources": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.5.0.tgz", + "integrity": "sha512-HPuy+uuoTCaaoEoI1LQ3JN9+vrPBvEesnnX1jADHy728cHSMlq4wUc4afYqahq2B1mhQVZxCXOkNTnXltr+2vQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/webpack/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/which-typed-array": { + "version": "1.1.22", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.22.tgz", + "integrity": "sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==", + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/workerpool": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", + "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/ws": { + "version": "7.5.11", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.11.tgz", + "integrity": "sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", + "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "16.2.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.2.tgz", + "integrity": "sha512-Nt9ZJjXTv5R8MHbqby/wXQ6Gi0Bb3TcYZkR1bzuL4yB2OxWPkXknz513gEF0GoA6tn00UpbPvERW8rzCuWCA6w==", + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yargs-unparser/node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", + "integrity": "sha512-uTv8J/wiWTgUTg+9vLTi//leUl5vDQS6uii/emeTb2ssY7vl6QWf2fFbIIGjnhjvbdKlU0ed7QPgY1htTC86jQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "packages/live-share": { + "name": "@microsoft/live-share", + "version": "2.0.0-internal.18", + "license": "SEE LICENSE IN LICENSE", + "dependencies": { + "@fluid-internal/client-utils": ">=2.40 <2.120", + "@fluidframework/aqueduct": ">=2.40 <2.120", + "@fluidframework/core-interfaces": ">=2.40 <2.120", + "@fluidframework/core-utils": ">=2.40 <2.120", + "@fluidframework/register-collection": ">=2.40 <2.120", + "uuid": "^9.0.0" + }, + "devDependencies": { + "@fluidframework/mocha-test-setup": "^2.0.0-rc.1.0.9", + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", + "@fluidframework/test-utils": ">=2.40 <2.120", + "@live-share-private/test-utils": "^1.0.0", + "@types/assert": "^1.5.6", + "@types/mocha": "^10.0.1", + "@types/node": "^20.2.3", + "@types/uuid": "9.0.1", + "fluid-framework": ">=2.40 <2.120", + "mocha": "^10.2.0", + "nyc": "^15.1.0", + "start-server-and-test": "^2.0.4", + "ts-mocha": "^10.0.0", + "typescript": "~5.5.3" + }, + "peerDependencies": { + "@fluidframework/azure-client": ">=2.40 <2.120", + "fluid-framework": ">=2.40 <2.120" + } + }, + "packages/live-share-acs": { + "name": "@microsoft/live-share-acs", + "version": "2.0.0-internal.18", + "license": "SEE LICENSE IN LICENSE", + "devDependencies": { + "@azure/communication-calling": "^1.27.3", + "@microsoft/live-share": "2.0.0-internal.18", + "@types/assert": "^1.5.6", + "@types/mocha": "^10.0.1", + "@types/node": "^20.2.3", + "mocha": "^10.2.0", + "nyc": "^15.1.0", + "ts-mocha": "^10.0.0", + "typescript": "~5.5.3" + }, + "peerDependencies": { + "@azure/communication-calling": "^1.14.0", + "@microsoft/live-share": "2.0.0-internal.18" + } + }, + "packages/live-share-acs/node_modules/@types/node": { + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "packages/live-share-acs/node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "packages/live-share-canvas": { + "name": "@microsoft/live-share-canvas", + "version": "2.0.0-internal.18", + "license": "SEE LICENSE IN LICENSE", + "devDependencies": { + "@microsoft/live-share": "2.0.0-internal.18", + "@types/assert": "^1.5.6", + "@types/mocha": "^10.0.1", + "@types/node": "^20.2.3", + "fluid-framework": ">=2.40 <2.120", + "mocha": "^10.2.0", + "nyc": "^15.1.0", + "ts-mocha": "^10.0.0", + "typescript": "~5.5.3" + }, + "peerDependencies": { + "@microsoft/live-share": "2.0.0-internal.18", + "fluid-framework": ">=2.40 <2.120" + } + }, + "packages/live-share-canvas/node_modules/@types/node": { + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "packages/live-share-canvas/node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "packages/live-share-media": { + "name": "@microsoft/live-share-media", + "version": "2.0.0-internal.18", + "license": "SEE LICENSE IN LICENSE", + "devDependencies": { + "@fluidframework/mocha-test-setup": "^2.0.0-rc.1.0.9", + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", + "@fluidframework/test-utils": ">=2.40 <2.120", + "@live-share-private/test-utils": "^1.0.0", + "@microsoft/live-share": "2.0.0-internal.18", + "@types/assert": "^1.5.6", + "@types/mocha": "^10.0.1", + "@types/node": "^20.2.3", + "fluid-framework": ">=2.40 <2.120", + "mocha": "^10.2.0", + "nyc": "^15.1.0", + "ts-mocha": "^10.0.0", + "typescript": "~5.5.3" + }, + "peerDependencies": { + "@microsoft/live-share": "2.0.0-internal.18", + "fluid-framework": ">=2.40 <2.120" + } + }, + "packages/live-share-media/node_modules/@types/node": { + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "packages/live-share-media/node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "packages/live-share-react": { + "name": "@microsoft/live-share-react", + "version": "2.0.0-internal.18", + "license": "SEE LICENSE IN LICENSE", + "dependencies": { + "url": "^0.11.0", + "uuid": "^9.0.0" + }, + "devDependencies": { + "@babel/core": "^7.21.8", + "@microsoft/live-share": "2.0.0-internal.18", + "@microsoft/live-share-canvas": "2.0.0-internal.18", + "@microsoft/live-share-media": "2.0.0-internal.18", + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.0", + "@types/uuid": "^9.0.1", + "babel-loader": "^9.1.2", + "fluid-framework": ">=2.40 <2.120", + "typescript": "~5.5.3" + }, + "peerDependencies": { + "@microsoft/live-share": "2.0.0-internal.18", + "@microsoft/live-share-canvas": "2.0.0-internal.18", + "@microsoft/live-share-media": "2.0.0-internal.18", + "fluid-framework": ">=2.40 <2.120", + "react": "^16.8.0 || ^17 || ^18", + "react-dom": "^16.8.0 || ^17 || ^18" + } + }, + "packages/live-share/node_modules/@types/node": { + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "packages/live-share/node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "samples/javascript/01.dice-roller": { + "name": "@microsoft/01.dice-roller", + "version": "1.0.0", + "license": "Microsoft", + "dependencies": { + "@fluidframework/azure-client": ">=2.40 <2.120", + "@microsoft/live-share": "2.0.0-internal.18", + "@microsoft/teams-js": "^2.16.0", + "fluid-framework": ">=2.40 <2.120" + }, + "devDependencies": { + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "buffer": "^6.0.3", + "start-server-and-test": "^2.0.0", + "vite": "^6.1.7" + } + }, + "samples/javascript/02.react-video": { + "name": "react-video", + "version": "1.0.0", + "license": "Microsoft", + "dependencies": { + "@fluentui/react-components": "^9.18.6", + "@fluentui/react-icons": "^2.0.202", + "@fluentui/react-theme": "^9.1.5", + "@fluidframework/azure-client": ">=2.40 <2.120", + "@microsoft/live-share": "2.0.0-internal.18", + "@microsoft/live-share-media": "2.0.0-internal.18", + "@microsoft/teams-js": "^2.16.0", + "@testing-library/jest-dom": "^5.16.5", + "@testing-library/react": "^13.4.0", + "@testing-library/user-event": "^14.4.3", + "fluid-framework": ">=2.40 <2.120", + "lodash": "^4.17.21", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router": "^6.4.2", + "react-router-dom": "^6.4.2", + "use-resize-observer": "^9.1.0", + "uuid": "^9.0.0", + "web-vitals": "^3.1.1" + }, + "devDependencies": { + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "@vitejs/plugin-react": "^5.1.4", + "chalk": "^5.2.0", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-react": "^7.34.4", + "jest-puppeteer": "^11.0.0", + "prettier": "^3.3.3", + "puppeteer": "^24.34.0", + "rimraf": "^2.6.3", + "start-server-and-test": "^2.0.0", + "vite": "^6.1.7" + } + }, + "samples/javascript/02.react-video/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "samples/javascript/02.react-video/node_modules/chalk": { + "version": "5.6.2", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "samples/javascript/02.react-video/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "samples/javascript/02.react-video/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "samples/javascript/02.react-video/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "samples/javascript/03.live-canvas-demo": { + "name": "@microsoft/03.live-canvas-demo", + "version": "1.0.0", + "license": "SEE LICENSE IN LICENSE", + "dependencies": { + "@fluidframework/azure-client": ">=2.40 <2.120", + "@microsoft/live-share": "2.0.0-internal.18", + "@microsoft/live-share-canvas": "2.0.0-internal.18", + "@microsoft/teams-js": "^2.16.0", + "fluid-framework": ">=2.40 <2.120" + }, + "devDependencies": { + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "buffer": "^6.0.3", + "start-server-and-test": "^2.0.0", + "vite": "^6.1.7" + } + }, + "samples/javascript/04.live-share-react": { + "name": "@microsoft/04.live-share-react-sample", + "version": "0.4.0", + "license": "MIT", + "dependencies": { + "@fluentui/react-components": "^9.18.6", + "@fluentui/react-icons": "^2.0.202", + "@fluentui/react-theme": "^9.1.5", + "@fluidframework/azure-client": ">=2.40 <2.120", + "@microsoft/live-share": "2.0.0-internal.18", + "@microsoft/live-share-canvas": "2.0.0-internal.18", + "@microsoft/live-share-media": "2.0.0-internal.18", + "@microsoft/live-share-react": "2.0.0-internal.18", + "@microsoft/teams-js": "^2.16.0", + "fluid-framework": ">=2.40 <2.120", + "lodash": "^4.17.21", + "prop-types": "^15.8.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router": "^6.4.2", + "react-router-dom": "^6.4.2", + "use-resize-observer": "^9.1.0", + "uuid": "^9.0.0", + "web-vitals": "^3.1.1" + }, + "devDependencies": { + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", + "@testing-library/jest-dom": "^5.16.5", + "@testing-library/react": "^13.4.0", + "@testing-library/user-event": "^14.4.3", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "@vitejs/plugin-react": "^5.1.4", + "dotenv-cli": "^7.2.1", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.1.3", + "prettier": "^3.3.3", + "start-server-and-test": "^2.0.0", + "vite": "^6.1.7" + } + }, + "samples/javascript/05.dice-roller-turbo": { + "name": "@microsoft/05.dice-roller-turbo", + "version": "1.0.0", + "license": "Microsoft", + "dependencies": { + "@fluidframework/azure-client": ">=2.40 <2.120", + "@microsoft/live-share": "2.0.0-internal.18", + "@microsoft/teams-js": "^2.16.0", + "fluid-framework": ">=2.40 <2.120" + }, + "devDependencies": { + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "buffer": "^6.0.3", + "start-server-and-test": "^2.0.0", + "vite": "^6.1.7" + } + }, + "samples/javascript/21.react-media-template": { + "name": "@microsoft/21.react-media-template", + "version": "0.4.0", + "license": "MIT", + "dependencies": { + "@fluentui/react-components": "^9.18.6", + "@fluentui/react-icons": "^2.0.202", + "@fluentui/react-theme": "^9.1.5", + "@fluidframework/azure-client": ">=2.40 <2.120", + "@microsoft/live-share": "2.0.0-internal.18", + "@microsoft/live-share-canvas": "2.0.0-internal.18", + "@microsoft/live-share-media": "2.0.0-internal.18", + "@microsoft/teams-js": "^2.16.0", + "fluid-framework": ">=2.40 <2.120", + "lodash": "^4.17.21", + "prop-types": "^15.8.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router": "^6.4.2", + "react-router-dom": "^6.4.2", + "use-resize-observer": "^9.1.0", + "uuid": "^9.0.0", + "web-vitals": "^3.1.1" + }, + "devDependencies": { + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", + "@testing-library/jest-dom": "^5.16.5", + "@testing-library/react": "^13.4.0", + "@testing-library/user-event": "^14.4.3", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "@vitejs/plugin-react": "^5.1.4", + "dotenv-cli": "^7.2.1", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.1.3", + "prettier": "^3.3.3", + "start-server-and-test": "^2.0.0", + "vite": "^6.1.7" + } + }, + "samples/javascript/22.react-agile-poker": { + "name": "@microsoft/22.react-agile-poker", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "@fluentui/react-components": "^9.18.6", + "@fluentui/react-icons": "^2.0.202", + "@fluentui/react-theme": "^9.1.5", + "@fluidframework/azure-client": ">=2.40 <2.120", + "@microsoft/live-share": "2.0.0-internal.18", + "@microsoft/teams-js": "^2.16.0", + "fluid-framework": ">=2.40 <2.120", + "prop-types": "^15.8.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router": "^6.4.2", + "react-router-dom": "^6.4.2", + "uuid": "^9.0.0", + "web-vitals": "^3.1.1" + }, + "devDependencies": { + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", + "@testing-library/jest-dom": "^5.16.5", + "@testing-library/react": "^13.4.0", + "@testing-library/user-event": "^14.4.3", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "@vitejs/plugin-react": "^5.1.4", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.1.3", + "prettier": "^3.3.3", + "start-server-and-test": "^2.0.0", + "vite": "^6.1.7" + } + }, + "samples/javascript/23.react-live-canvas": { + "name": "@microsoft/23.react-live-canvas", + "version": "0.4.0", + "license": "MIT", + "dependencies": { + "@fluidframework/azure-client": ">=2.40 <2.120", + "@microsoft/live-share": "2.0.0-internal.18", + "@microsoft/live-share-canvas": "2.0.0-internal.18", + "@microsoft/teams-js": "^2.16.0", + "fluid-framework": ">=2.40 <2.120", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router": "^6.4.2", + "react-router-dom": "^6.4.2", + "uuid": "^9.0.0", + "web-vitals": "^3.1.1" + }, + "devDependencies": { + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", + "@testing-library/jest-dom": "^5.16.5", + "@testing-library/react": "^13.4.0", + "@testing-library/user-event": "^14.4.3", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "@vitejs/plugin-react": "^5.1.4", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.1.3", + "prettier": "^3.3.3", + "start-server-and-test": "^2.0.0", + "vite": "^6.1.7" + } + }, + "samples/typescript/01.dice-roller": { + "name": "@microsoft/01.dice-roller-ts", + "version": "1.0.0", + "license": "Microsoft", + "dependencies": { + "@fluidframework/azure-client": ">=2.40 <2.120", + "@microsoft/live-share": "2.0.0-internal.18", + "@microsoft/teams-js": "^2.16.0", + "fluid-framework": ">=2.40 <2.120" + }, + "devDependencies": { + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "buffer": "^6.0.3", + "start-server-and-test": "^2.0.0", + "vite": "^6.1.7" + } + }, + "samples/typescript/03.live-canvas-demo": { + "name": "@microsoft/03.live-canvas-demo-ts", + "version": "1.0.0", + "license": "SEE LICENSE IN LICENSE", + "dependencies": { + "@fluidframework/azure-client": ">=2.40 <2.120", + "@microsoft/live-share": "2.0.0-internal.18", + "@microsoft/live-share-canvas": "2.0.0-internal.18", + "@microsoft/teams-js": "^2.16.0", + "fluid-framework": ">=2.40 <2.120" + }, + "devDependencies": { + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "buffer": "^6.0.3", + "start-server-and-test": "^2.0.0", + "vite": "^6.1.7" + } + }, + "samples/typescript/04.live-share-react": { + "name": "@microsoft/04.live-share-react-sample-ts", + "version": "0.4.0", + "license": "MIT", + "dependencies": { + "@fluentui/react-components": "^9.18.6", + "@fluentui/react-icons": "^2.0.202", + "@fluentui/react-theme": "^9.1.5", + "@fluidframework/azure-client": ">=2.40 <2.120", + "@microsoft/live-share": "2.0.0-internal.18", + "@microsoft/live-share-canvas": "2.0.0-internal.18", + "@microsoft/live-share-media": "2.0.0-internal.18", + "@microsoft/live-share-react": "2.0.0-internal.18", + "@microsoft/teams-js": "^2.16.0", + "fluid-framework": ">=2.40 <2.120", + "lodash": "^4.17.21", + "prop-types": "^15.8.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router": "^6.4.2", + "react-router-dom": "^6.4.2", + "use-resize-observer": "^9.1.0", + "uuid": "^9.0.0", + "web-vitals": "^3.1.1" + }, + "devDependencies": { + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", + "@testing-library/jest-dom": "^5.16.5", + "@testing-library/react": "^13.4.0", + "@testing-library/user-event": "^14.4.3", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "@vitejs/plugin-react": "^5.1.4", + "dotenv-cli": "^7.2.1", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.1.3", + "prettier": "^3.3.3", + "start-server-and-test": "^2.0.0", + "vite": "^6.1.7" + } + }, + "samples/typescript/05.dice-roller-turbo": { + "name": "@microsoft/05.dice-roller-turbo-ts", + "version": "1.0.0", + "license": "Microsoft", + "dependencies": { + "@fluidframework/azure-client": ">=2.40 <2.120", + "@microsoft/live-share": "2.0.0-internal.18", + "@microsoft/teams-js": "^2.16.0", + "fluid-framework": ">=2.40 <2.120" + }, + "devDependencies": { + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "buffer": "^6.0.3", + "start-server-and-test": "^2.0.0", + "vite": "^6.1.7" + } + }, + "samples/typescript/06.presence-avatars": { + "name": "@microsoft/06.presence-avatars", + "version": "0.4.0", + "license": "MIT", + "dependencies": { + "@fluentui/react-components": "^9.18.6", + "@fluentui/react-icons": "^2.0.202", + "@fluentui/react-theme": "^9.1.5", + "@fluidframework/azure-client": ">=2.40 <2.120", + "@microsoft/live-share": "2.0.0-internal.18", + "@microsoft/live-share-canvas": "2.0.0-internal.18", + "@microsoft/live-share-media": "2.0.0-internal.18", + "@microsoft/live-share-react": "2.0.0-internal.18", + "@microsoft/teams-js": "^2.16.0", + "fluid-framework": ">=2.40 <2.120", + "lodash": "^4.17.21", + "prop-types": "^15.8.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router": "^6.4.2", + "react-router-dom": "^6.4.2", + "use-resize-observer": "^9.1.0", + "uuid": "^9.0.0", + "web-vitals": "^3.1.1" + }, + "devDependencies": { + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", + "@testing-library/jest-dom": "^5.16.5", + "@testing-library/react": "^13.4.0", + "@testing-library/user-event": "^14.4.3", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "@vitejs/plugin-react": "^5.1.4", + "dotenv-cli": "^7.2.1", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.1.3", + "prettier": "^3.3.3", + "start-server-and-test": "^2.0.0", + "vite": "^6.1.7" + } + }, + "samples/typescript/07.countdown-timer": { + "name": "@microsoft/07.countdown-timer", + "version": "0.4.0", + "license": "MIT", + "dependencies": { + "@fluentui/react-components": "^9.18.6", + "@fluentui/react-icons": "^2.0.202", + "@fluentui/react-theme": "^9.1.5", + "@fluidframework/azure-client": ">=2.40 <2.120", + "@microsoft/live-share": "2.0.0-internal.18", + "@microsoft/live-share-canvas": "2.0.0-internal.18", + "@microsoft/live-share-media": "2.0.0-internal.18", + "@microsoft/live-share-react": "2.0.0-internal.18", + "@microsoft/teams-js": "^2.16.0", + "fluid-framework": ">=2.40 <2.120", + "lodash": "^4.17.21", + "prop-types": "^15.8.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router": "^6.4.2", + "react-router-dom": "^6.4.2", + "use-resize-observer": "^9.1.0", + "uuid": "^9.0.0", + "web-vitals": "^3.1.1" + }, + "devDependencies": { + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", + "@testing-library/jest-dom": "^5.16.5", + "@testing-library/react": "^13.4.0", + "@testing-library/user-event": "^14.4.3", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "@vitejs/plugin-react": "^5.1.4", + "dotenv-cli": "^7.2.1", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.1.3", + "prettier": "^3.3.3", + "start-server-and-test": "^2.0.0", + "vite": "^6.1.7" + } + }, + "samples/typescript/08.3d-model": { + "name": "@microsoft/08.3d-model", + "version": "0.4.0", + "license": "MIT", + "dependencies": { + "@babylonjs/core": "6.43.0", + "@babylonjs/gui": "6.43.0", + "@babylonjs/loaders": "6.43.0", + "@fluentui/react-components": "^9.18.6", + "@fluentui/react-icons": "^2.0.202", + "@fluentui/react-theme": "^9.1.5", + "@fluidframework/azure-client": ">=2.40 <2.120", + "@microsoft/live-share": "2.0.0-internal.18", + "@microsoft/live-share-canvas": "2.0.0-internal.18", + "@microsoft/live-share-media": "2.0.0-internal.18", + "@microsoft/live-share-react": "2.0.0-internal.18", + "@microsoft/teams-js": "^2.16.0", + "fluid-framework": ">=2.40 <2.120", + "lodash": "^4.17.21", + "prop-types": "^15.8.1", + "react": "^18.2.0", + "react-babylonjs": "3.1.27", + "react-colorful": "^5.6.1", + "react-dom": "^18.2.0", + "react-router": "^6.4.2", + "react-router-dom": "^6.4.2", + "use-resize-observer": "^9.1.0", + "uuid": "^9.0.0", + "web-vitals": "^3.1.1" + }, + "devDependencies": { + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", + "@testing-library/jest-dom": "^5.16.5", + "@testing-library/react": "^13.4.0", + "@testing-library/user-event": "^14.4.3", + "@types/babylonjs": "2.4.1", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "@vitejs/plugin-react": "^5.1.4", + "dotenv-cli": "^7.2.1", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.1.3", + "prettier": "^3.3.3", + "start-server-and-test": "^2.0.0", + "vite": "^6.1.7" } }, - "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", - "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "samples/typescript/11.react-video-js": { + "name": "react-video-js", + "version": "0.4.0", + "license": "MIT", + "dependencies": { + "@fluentui/react-components": "^9.18.6", + "@fluentui/react-icons": "^2.0.202", + "@fluentui/react-theme": "^9.1.5", + "@fluidframework/azure-client": ">=2.40 <2.120", + "@microsoft/live-share": "2.0.0-internal.18", + "@microsoft/live-share-canvas": "2.0.0-internal.18", + "@microsoft/live-share-media": "2.0.0-internal.18", + "@microsoft/teams-js": "^2.16.0", + "fluid-framework": ">=2.40 <2.120", + "lodash": "^4.17.21", + "prop-types": "^15.8.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router": "^6.4.2", + "react-router-dom": "^6.4.2", + "use-resize-observer": "^9.1.0", + "uuid": "^9.0.0", + "video.js": "^8.17.4", + "web-vitals": "^3.1.1" + }, + "devDependencies": { + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", + "@testing-library/jest-dom": "^5.16.5", + "@testing-library/react": "^13.4.0", + "@testing-library/user-event": "^14.4.3", + "@types/lodash": "^4.14.191", + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.0", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "@vitejs/plugin-react": "^5.1.4", + "dotenv-cli": "^7.2.1", + "esbuild": "^0.27.2", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-react": "^7.34.4", + "eslint-plugin-react-hooks": "^4.6.2", + "start-server-and-test": "^2.0.0", + "vite": "^6.1.7" } }, - "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", - "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "samples/typescript/11.react-video-js/node_modules/@esbuild/aix-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", + "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", "cpu": [ - "loong64" + "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ - "linux" + "aix" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", - "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "samples/typescript/11.react-video-js/node_modules/@esbuild/android-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", + "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", "cpu": [ - "mips64el" + "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ - "linux" + "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", - "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", + "samples/typescript/11.react-video-js/node_modules/@esbuild/android-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", + "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", "cpu": [ - "ppc64" + "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ - "linux" + "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", - "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", + "samples/typescript/11.react-video-js/node_modules/@esbuild/android-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", + "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", "cpu": [ - "riscv64" + "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ - "linux" + "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", - "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", + "samples/typescript/11.react-video-js/node_modules/@esbuild/darwin-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", + "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", "cpu": [ - "s390x" + "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ - "linux" + "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/linux-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "samples/typescript/11.react-video-js/node_modules/@esbuild/darwin-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", + "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ - "linux" + "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", - "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", + "samples/typescript/11.react-video-js/node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", + "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", "cpu": [ - "x64" + "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ - "netbsd" + "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", - "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", + "samples/typescript/11.react-video-js/node_modules/@esbuild/freebsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", + "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ - "openbsd" + "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", - "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", + "samples/typescript/11.react-video-js/node_modules/@esbuild/linux-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", + "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", "cpu": [ - "x64" + "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ - "sunos" + "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", - "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", + "samples/typescript/11.react-video-js/node_modules/@esbuild/linux-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", + "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ - "win32" + "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", - "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", + "samples/typescript/11.react-video-js/node_modules/@esbuild/linux-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", + "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ - "win32" + "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/win32-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", - "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "samples/typescript/11.react-video-js/node_modules/@esbuild/linux-loong64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", + "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", "cpu": [ - "x64" + "loong64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ - "win32" + "linux" ], "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/esbuild": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", - "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/android-arm": "0.18.20", - "@esbuild/android-arm64": "0.18.20", - "@esbuild/android-x64": "0.18.20", - "@esbuild/darwin-arm64": "0.18.20", - "@esbuild/darwin-x64": "0.18.20", - "@esbuild/freebsd-arm64": "0.18.20", - "@esbuild/freebsd-x64": "0.18.20", - "@esbuild/linux-arm": "0.18.20", - "@esbuild/linux-arm64": "0.18.20", - "@esbuild/linux-ia32": "0.18.20", - "@esbuild/linux-loong64": "0.18.20", - "@esbuild/linux-mips64el": "0.18.20", - "@esbuild/linux-ppc64": "0.18.20", - "@esbuild/linux-riscv64": "0.18.20", - "@esbuild/linux-s390x": "0.18.20", - "@esbuild/linux-x64": "0.18.20", - "@esbuild/netbsd-x64": "0.18.20", - "@esbuild/openbsd-x64": "0.18.20", - "@esbuild/sunos-x64": "0.18.20", - "@esbuild/win32-arm64": "0.18.20", - "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" - } - }, - "node_modules/vscode-oniguruma": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", - "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", - "dev": true - }, - "node_modules/vscode-textmate": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", - "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", - "dev": true - }, - "node_modules/w3c-xmlserializer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", - "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", - "dev": true, - "dependencies": { - "xml-name-validator": "^4.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/wait-on": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-6.0.1.tgz", - "integrity": "sha512-zht+KASY3usTY5u2LgaNqn/Cd8MukxLGjdcZxT2ns5QzDmTFc4XoWBgC+C/na+sMRZTuVygQoMYwdcVjHnYIVw==", - "dev": true, - "dependencies": { - "axios": "^0.25.0", - "joi": "^17.6.0", - "lodash": "^4.17.21", - "minimist": "^1.2.5", - "rxjs": "^7.5.4" - }, - "bin": { - "wait-on": "bin/wait-on" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/wait-on/node_modules/axios": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz", - "integrity": "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==", - "dev": true, - "dependencies": { - "follow-redirects": "^1.14.7" - } - }, - "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "dev": true, - "peer": true, - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/web-vitals": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-3.3.1.tgz", - "integrity": "sha512-LTfY5GjcY3ngFzNsYFSYL+AmVmlWrzPTUxSMDis2rZbf+SzT7HH3NH4Y/l45XOlrAIunOBeURN9qtBHkRskAiA==" - }, - "node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/webpack": { - "version": "5.83.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.83.1.tgz", - "integrity": "sha512-TNsG9jDScbNuB+Lb/3+vYolPplCS3bbEaJf+Bj0Gw4DhP3ioAflBb1flcRt9zsWITyvOhM96wMQNRWlSX52DgA==", - "dev": true, - "peer": true, - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.14.0", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.2", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, - "peer": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack/node_modules/schema-utils": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz", - "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==", - "dev": true, - "peer": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/whatwg-encoding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", - "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", - "dev": true, - "dependencies": { - "iconv-lite": "0.6.3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/whatwg-mimetype": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/whatwg-url": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-12.0.1.tgz", - "integrity": "sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ==", - "dev": true, - "dependencies": { - "tr46": "^4.1.1", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=14" + "node": ">=18" } }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "samples/typescript/11.react-video-js/node_modules/@esbuild/linux-mips64el": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", + "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", + "cpu": [ + "mips64el" + ], "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=18" } }, - "node_modules/which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", - "dependencies": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "samples/typescript/11.react-video-js/node_modules/@esbuild/linux-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", + "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/which-module": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", - "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", - "dev": true - }, - "node_modules/which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" - }, + "samples/typescript/11.react-video-js/node_modules/@esbuild/linux-riscv64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", + "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=18" } }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "samples/typescript/11.react-video-js/node_modules/@esbuild/linux-s390x": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", + "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", + "cpu": [ + "s390x" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.10.0" + "node": ">=18" } }, - "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "samples/typescript/11.react-video-js/node_modules/@esbuild/linux-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", + "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": ">=18" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "samples/typescript/11.react-video-js/node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", + "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" } }, - "node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "samples/typescript/11.react-video-js/node_modules/@esbuild/netbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", + "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", + "cpu": [ + "x64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "node": ">=18" } }, - "node_modules/xml-name-validator": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", - "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "samples/typescript/11.react-video-js/node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", + "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", + "cpu": [ + "arm64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true - }, - "node_modules/xmlhttprequest-ssl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", - "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==", + "samples/typescript/11.react-video-js/node_modules/@esbuild/openbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", + "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=0.4.0" + "node": ">=18" } }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "samples/typescript/11.react-video-js/node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", + "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", + "cpu": [ + "arm64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "samples/typescript/11.react-video-js/node_modules/@esbuild/sunos-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", + "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "samples/typescript/11.react-video-js/node_modules/@esbuild/win32-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", + "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", + "cpu": [ + "arm64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "samples/typescript/11.react-video-js/node_modules/@esbuild/win32-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", + "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "samples/typescript/11.react-video-js/node_modules/@esbuild/win32-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", + "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", + "cpu": [ + "x64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=18" } }, - "node_modules/yargs-unparser/node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "samples/typescript/11.react-video-js/node_modules/esbuild": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", + "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, "engines": { - "node": ">=10" + "node": ">=18" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.7", + "@esbuild/android-arm": "0.27.7", + "@esbuild/android-arm64": "0.27.7", + "@esbuild/android-x64": "0.27.7", + "@esbuild/darwin-arm64": "0.27.7", + "@esbuild/darwin-x64": "0.27.7", + "@esbuild/freebsd-arm64": "0.27.7", + "@esbuild/freebsd-x64": "0.27.7", + "@esbuild/linux-arm": "0.27.7", + "@esbuild/linux-arm64": "0.27.7", + "@esbuild/linux-ia32": "0.27.7", + "@esbuild/linux-loong64": "0.27.7", + "@esbuild/linux-mips64el": "0.27.7", + "@esbuild/linux-ppc64": "0.27.7", + "@esbuild/linux-riscv64": "0.27.7", + "@esbuild/linux-s390x": "0.27.7", + "@esbuild/linux-x64": "0.27.7", + "@esbuild/netbsd-arm64": "0.27.7", + "@esbuild/netbsd-x64": "0.27.7", + "@esbuild/openbsd-arm64": "0.27.7", + "@esbuild/openbsd-x64": "0.27.7", + "@esbuild/openharmony-arm64": "0.27.7", + "@esbuild/sunos-x64": "0.27.7", + "@esbuild/win32-arm64": "0.27.7", + "@esbuild/win32-ia32": "0.27.7", + "@esbuild/win32-x64": "0.27.7" } }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, + "samples/typescript/21.react-media-template": { + "name": "react-media-template-ts", + "version": "0.4.0", + "license": "MIT", "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" + "@fluentui/react-components": "^9.18.6", + "@fluentui/react-icons": "^2.0.202", + "@fluentui/react-theme": "^9.1.5", + "@fluidframework/azure-client": ">=2.40 <2.120", + "@microsoft/live-share": "2.0.0-internal.18", + "@microsoft/live-share-canvas": "2.0.0-internal.18", + "@microsoft/live-share-media": "2.0.0-internal.18", + "@microsoft/teams-js": "^2.16.0", + "fluid-framework": ">=2.40 <2.120", + "lodash": "^4.17.21", + "prop-types": "^15.8.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router": "^6.4.2", + "react-router-dom": "^6.4.2", + "use-resize-observer": "^9.1.0", + "uuid": "^9.0.0", + "web-vitals": "^3.1.1" + }, + "devDependencies": { + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", + "@testing-library/jest-dom": "^5.16.5", + "@testing-library/react": "^13.4.0", + "@testing-library/user-event": "^14.4.3", + "@types/lodash": "^4.14.191", + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.0", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "@vitejs/plugin-react": "^5.1.4", + "dotenv-cli": "^7.2.1", + "esbuild": "^0.27.2", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-react": "^7.34.4", + "eslint-plugin-react-hooks": "^4.6.2", + "start-server-and-test": "^2.0.0", + "vite": "^6.1.7" } }, - "node_modules/yn": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", - "integrity": "sha512-uTv8J/wiWTgUTg+9vLTi//leUl5vDQS6uii/emeTb2ssY7vl6QWf2fFbIIGjnhjvbdKlU0ed7QPgY1htTC86jQ==", + "samples/typescript/21.react-media-template/node_modules/@esbuild/aix-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", + "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", + "cpu": [ + "ppc64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": ">=4" + "node": ">=18" } }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "samples/typescript/21.react-media-template/node_modules/@esbuild/android-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", + "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", + "cpu": [ + "arm" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "packages/live-share": { - "name": "@microsoft/live-share", - "version": "1.4.0", - "license": "SEE LICENSE IN LICENSE", - "dependencies": { - "uuid": "^9.0.0" - }, - "devDependencies": { - "@fluidframework/azure-client": "^1.1.1", - "@fluidframework/test-client-utils": "^1.3.6", - "@fluidframework/test-runtime-utils": "^1.3.6", - "@fluidframework/test-utils": "^1.3.6", - "@fluidframework/test-version-utils": "^1.3.6", - "@types/assert": "^1.5.6", - "@types/mocha": "^10.0.1", - "@types/node": "^20.2.3", - "@types/uuid": "9.0.1", - "fluid-framework": "^1.3.6", - "mocha": "^10.2.0", - "nyc": "^15.1.0", - "ts-mocha": "^10.0.0", - "typescript": "^5.0.4" - }, - "peerDependencies": { - "@fluidframework/azure-client": "^1.0.0", - "fluid-framework": "^1.2.3" + "node": ">=18" } }, - "packages/live-share-acs": { - "version": "1.4.0-preview.0", - "license": "SEE LICENSE IN LICENSE", - "devDependencies": { - "@azure/communication-calling": "^1.14.0", - "@microsoft/live-share": "1.4.0", - "@types/assert": "^1.5.6", - "@types/mocha": "^10.0.1", - "@types/node": "^18.11.18", - "mocha": "^10.2.0", - "nyc": "^15.1.0", - "ts-mocha": "^10.0.0", - "typescript": "^4.6.4" - }, - "peerDependencies": { - "@azure/communication-calling": "^1.14.0", - "@microsoft/live-share": "1.4.0" + "samples/typescript/21.react-media-template/node_modules/@esbuild/android-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", + "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" } }, - "packages/live-share-acs/node_modules/@types/node": { - "version": "18.19.31", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.31.tgz", - "integrity": "sha512-ArgCD39YpyyrtFKIqMDvjz79jto5fcI/SVUs2HwB+f0dAzq68yqOdyaSivLiLugSziTpNXLQrVb7RZFmdZzbhA==", + "samples/typescript/21.react-media-template/node_modules/@esbuild/android-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", + "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "undici-types": "~5.26.4" + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" } }, - "packages/live-share-acs/node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "samples/typescript/21.react-media-template/node_modules/@esbuild/darwin-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", + "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", + "cpu": [ + "arm64" + ], "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=4.2.0" + "node": ">=18" } }, - "packages/live-share-canvas": { - "name": "@microsoft/live-share-canvas", - "version": "1.4.0", - "license": "SEE LICENSE IN LICENSE", - "devDependencies": { - "@microsoft/live-share": "1.4.0", - "@types/assert": "^1.5.6", - "@types/mocha": "^10.0.1", - "@types/node": "^20.2.3", - "fluid-framework": "^1.3.6", - "mocha": "^10.2.0", - "nyc": "^15.1.0", - "ts-mocha": "^10.0.0", - "typescript": "^5.0.4" - }, - "peerDependencies": { - "@microsoft/live-share": "1.4.0", - "fluid-framework": "^1.2.3" + "samples/typescript/21.react-media-template/node_modules/@esbuild/darwin-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", + "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" } }, - "packages/live-share-media": { - "name": "@microsoft/live-share-media", - "version": "1.4.0", - "license": "SEE LICENSE IN LICENSE", - "devDependencies": { - "@fluidframework/test-client-utils": "^1.3.6", - "@fluidframework/test-runtime-utils": "^1.3.6", - "@fluidframework/test-utils": "^1.3.6", - "@fluidframework/test-version-utils": "^1.3.6", - "@microsoft/live-share": "1.4.0", - "@types/assert": "^1.5.6", - "@types/mocha": "^10.0.1", - "@types/node": "^20.2.3", - "fluid-framework": "^1.3.6", - "mocha": "^10.2.0", - "nyc": "^15.1.0", - "ts-mocha": "^10.0.0", - "typescript": "^5.0.4" - }, - "peerDependencies": { - "@microsoft/live-share": "1.4.0", - "fluid-framework": "^1.2.3" + "samples/typescript/21.react-media-template/node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", + "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" } }, - "packages/live-share-react": { - "name": "@microsoft/live-share-react", - "version": "1.4.0-preview.0", - "license": "SEE LICENSE IN LICENSE", - "dependencies": { - "@microsoft/live-share-turbo": "1.4.0-preview.0", - "url": "^0.11.0", - "uuid": "^9.0.0" - }, - "devDependencies": { - "@babel/core": "^7.21.8", - "@fluidframework/azure-client": "^1.1.1", - "@fluidframework/test-client-utils": "^1.3.6", - "@microsoft/live-share": "1.4.0", - "@microsoft/live-share-canvas": "1.4.0", - "@microsoft/live-share-media": "1.4.0", - "@types/react": "^18.0.0", - "@types/react-dom": "^18.0.0", - "@types/uuid": "^9.0.1", - "babel-loader": "^9.1.2", - "fluid-framework": "^1.3.6", - "typescript": "^5.0.4" - }, - "peerDependencies": { - "@fluidframework/azure-client": "^1.0.0", - "@microsoft/live-share": "1.4.0", - "@microsoft/live-share-canvas": "1.4.0", - "@microsoft/live-share-media": "1.4.0", - "fluid-framework": "^1.2.3", - "react": "^16.8.0 || ^17 || ^18", - "react-dom": "^16.8.0 || ^17 || ^18" + "samples/typescript/21.react-media-template/node_modules/@esbuild/freebsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", + "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" } }, - "packages/live-share-turbo": { - "name": "@microsoft/live-share-turbo", - "version": "1.4.0-preview.0", - "license": "SEE LICENSE IN LICENSE", - "dependencies": { - "@fluidframework/register-collection": "^1.3.6" - }, - "devDependencies": { - "@fluidframework/azure-client": "^1.1.1", - "@fluidframework/test-client-utils": "^1.3.6", - "@fluidframework/test-runtime-utils": "^1.3.6", - "@fluidframework/test-utils": "^1.3.6", - "@fluidframework/test-version-utils": "^1.3.6", - "@microsoft/live-share": "1.4.0", - "@types/assert": "^1.5.6", - "@types/mocha": "^10.0.1", - "@types/node": "^20.2.3", - "@types/uuid": "9.0.1", - "fluid-framework": "^1.3.6", - "jsdom": "^21.1.0", - "jsdom-global": "^3.0.2", - "mocha": "^10.2.0", - "nyc": "^15.1.0", - "start-server-and-test": "^2.0.0", - "ts-mocha": "^10.0.0", - "typescript": "^5.0.4" - }, - "peerDependencies": { - "@fluidframework/azure-client": "^1.0.0", - "@microsoft/live-share": "1.4.0", - "fluid-framework": "^1.2.3" + "samples/typescript/21.react-media-template/node_modules/@esbuild/linux-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", + "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "samples/javascript/01.dice-roller": { - "name": "@microsoft/01.dice-roller", - "version": "1.0.0", - "hasInstallScript": true, - "license": "Microsoft", - "dependencies": { - "@fluidframework/azure-client": "^1.1.1", - "@microsoft/live-share": "1.4.0", - "@microsoft/teams-js": "^2.16.0", - "fluid-framework": "^1.3.6" - }, - "devDependencies": { - "@fluidframework/test-client-utils": "^1.3.6", - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.7", - "buffer": "^6.0.3", - "start-server-and-test": "^2.0.0", - "vite": "^4.0.4" + "samples/typescript/21.react-media-template/node_modules/@esbuild/linux-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", + "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "samples/javascript/02.react-video": { - "name": "react-video", - "version": "1.0.0", - "hasInstallScript": true, - "license": "Microsoft", - "dependencies": { - "@fluentui/react-components": "^9.18.6", - "@fluentui/react-icons": "^2.0.202", - "@fluentui/react-theme": "^9.1.5", - "@fluidframework/azure-client": "^1.1.1", - "@microsoft/live-share": "1.4.0", - "@microsoft/live-share-media": "1.4.0", - "@microsoft/teams-js": "^2.16.0", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^13.4.0", - "@testing-library/user-event": "^14.4.3", - "fluid-framework": "^1.3.6", - "lodash": "^4.17.21", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-router": "^6.4.2", - "react-router-dom": "^6.4.2", - "use-resize-observer": "^9.1.0", - "uuid": "^9.0.0", - "web-vitals": "^3.1.1" - }, - "devDependencies": { - "@fluidframework/test-client-utils": "^1.3.6", - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.7", - "@vitejs/plugin-react": "^3.0.1", - "chalk": "^5.2.0", - "eslint": "^8.41.0", - "eslint-config-prettier": "^8.8.0", - "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-react": "^7.32.2", - "jest-puppeteer": "^6.1.0", - "prettier": "^2.8.8", - "puppeteer": "^20.1.0", - "rimraf": "^2.6.3", - "start-server-and-test": "^2.0.0", - "vite": "^4.0.4" + "samples/typescript/21.react-media-template/node_modules/@esbuild/linux-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", + "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "samples/javascript/02.react-video/node_modules/chalk": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", - "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", + "samples/typescript/21.react-media-template/node_modules/@esbuild/linux-loong64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", + "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", + "cpu": [ + "loong64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=18" } }, - "samples/javascript/03.live-canvas-demo": { - "name": "@microsoft/03.live-canvas-demo", - "version": "1.0.0", - "hasInstallScript": true, - "license": "SEE LICENSE IN LICENSE", - "dependencies": { - "@fluidframework/azure-client": "^1.1.1", - "@microsoft/live-share": "1.4.0", - "@microsoft/live-share-canvas": "1.4.0", - "@microsoft/teams-js": "^2.16.0", - "fluid-framework": "^1.3.6" - }, - "devDependencies": { - "@fluidframework/test-client-utils": "^1.3.6", - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.7", - "buffer": "^6.0.3", - "start-server-and-test": "^2.0.0", - "vite": "^4.0.4" + "samples/typescript/21.react-media-template/node_modules/@esbuild/linux-mips64el": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", + "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "samples/javascript/04.live-share-react": { - "name": "@microsoft/04.live-share-react-sample", - "version": "0.4.0", - "hasInstallScript": true, + "samples/typescript/21.react-media-template/node_modules/@esbuild/linux-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", + "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", + "cpu": [ + "ppc64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@fluentui/react-components": "^9.18.6", - "@fluentui/react-icons": "^2.0.202", - "@fluentui/react-theme": "^9.1.5", - "@fluidframework/azure-client": "^1.1.1", - "@microsoft/live-share": "1.4.0", - "@microsoft/live-share-canvas": "1.4.0", - "@microsoft/live-share-media": "1.4.0", - "@microsoft/live-share-react": "1.4.0-preview.0", - "@microsoft/teams-js": "^2.16.0", - "fluid-framework": "^1.3.6", - "lodash": "^4.17.21", - "prop-types": "^15.8.1", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-router": "^6.4.2", - "react-router-dom": "^6.4.2", - "use-resize-observer": "^9.1.0", - "uuid": "^9.0.0", - "web-vitals": "^3.1.1" - }, - "devDependencies": { - "@fluidframework/test-client-utils": "^1.3.6", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^13.4.0", - "@testing-library/user-event": "^14.4.3", - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.7", - "@vitejs/plugin-react": "^3.0.1", - "dotenv-cli": "^7.2.1", - "eslint": "^8.41.0", - "eslint-config-prettier": "^8.8.0", - "eslint-plugin-prettier": "^4.2.1", - "prettier": "^2.8.8", - "start-server-and-test": "^2.0.0", - "vite": "^4.0.4" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "samples/javascript/05.dice-roller-turbo": { - "name": "@microsoft/05.dice-roller-turbo", - "version": "1.0.0", - "hasInstallScript": true, - "license": "Microsoft", - "dependencies": { - "@fluidframework/azure-client": "^1.1.1", - "@microsoft/live-share": "1.4.0", - "@microsoft/live-share-turbo": "1.4.0-preview.0", - "@microsoft/teams-js": "^2.16.0", - "fluid-framework": "^1.3.6" - }, - "devDependencies": { - "@fluidframework/test-client-utils": "^1.3.6", - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.7", - "buffer": "^6.0.3", - "start-server-and-test": "^2.0.0", - "vite": "^4.0.4" + "samples/typescript/21.react-media-template/node_modules/@esbuild/linux-riscv64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", + "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "samples/javascript/21.react-media-template": { - "name": "@microsoft/21.react-media-template", - "version": "0.4.0", - "hasInstallScript": true, + "samples/typescript/21.react-media-template/node_modules/@esbuild/linux-s390x": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", + "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", + "cpu": [ + "s390x" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@fluentui/react-components": "^9.18.6", - "@fluentui/react-icons": "^2.0.202", - "@fluentui/react-theme": "^9.1.5", - "@fluidframework/azure-client": "^1.1.1", - "@microsoft/live-share": "1.4.0", - "@microsoft/live-share-canvas": "1.4.0", - "@microsoft/live-share-media": "1.4.0", - "@microsoft/teams-js": "^2.16.0", - "fluid-framework": "^1.3.6", - "lodash": "^4.17.21", - "prop-types": "^15.8.1", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-router": "^6.4.2", - "react-router-dom": "^6.4.2", - "use-resize-observer": "^9.1.0", - "uuid": "^9.0.0", - "web-vitals": "^3.1.1" - }, - "devDependencies": { - "@fluidframework/test-client-utils": "^1.3.6", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^13.4.0", - "@testing-library/user-event": "^14.4.3", - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.7", - "@vitejs/plugin-react": "^3.0.1", - "dotenv-cli": "^7.2.1", - "eslint": "^8.41.0", - "eslint-config-prettier": "^8.8.0", - "eslint-plugin-prettier": "^4.2.1", - "prettier": "^2.8.8", - "start-server-and-test": "^2.0.0", - "vite": "^4.0.4" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "samples/javascript/22.react-agile-poker": { - "name": "@microsoft/22.react-agile-poker", - "version": "1.0.0", - "hasInstallScript": true, + "samples/typescript/21.react-media-template/node_modules/@esbuild/linux-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", + "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@fluentui/react-components": "^9.18.6", - "@fluentui/react-icons": "^2.0.202", - "@fluentui/react-theme": "^9.1.5", - "@fluidframework/azure-client": "^1.1.1", - "@microsoft/live-share": "1.4.0", - "@microsoft/teams-js": "^2.16.0", - "fluid-framework": "^1.3.6", - "prop-types": "^15.8.1", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-router": "^6.4.2", - "react-router-dom": "^6.4.2", - "uuid": "^9.0.0", - "web-vitals": "^3.1.1" - }, - "devDependencies": { - "@fluidframework/test-client-utils": "^1.3.6", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^13.4.0", - "@testing-library/user-event": "^14.4.3", - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.7", - "@vitejs/plugin-react": "^3.0.1", - "eslint": "^8.41.0", - "eslint-config-prettier": "^8.8.0", - "eslint-plugin-prettier": "^4.2.1", - "prettier": "^2.8.8", - "start-server-and-test": "^2.0.0", - "vite": "^4.0.4" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "samples/javascript/23.react-live-canvas": { - "name": "@microsoft/23.react-live-canvas", - "version": "0.4.0", - "hasInstallScript": true, + "samples/typescript/21.react-media-template/node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", + "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@fluidframework/azure-client": "^1.1.1", - "@microsoft/live-share": "1.4.0", - "@microsoft/live-share-canvas": "1.4.0", - "@microsoft/teams-js": "^2.16.0", - "fluid-framework": "^1.3.6", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-router": "^6.4.2", - "react-router-dom": "^6.4.2", - "uuid": "^9.0.0", - "web-vitals": "^3.1.1" - }, - "devDependencies": { - "@fluidframework/test-client-utils": "^1.3.6", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^13.4.0", - "@testing-library/user-event": "^14.4.3", - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.7", - "@vitejs/plugin-react": "^3.0.1", - "eslint": "^8.41.0", - "eslint-config-prettier": "^8.8.0", - "eslint-plugin-prettier": "^4.2.1", - "prettier": "^2.8.8", - "start-server-and-test": "^2.0.0", - "vite": "^4.0.4" + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" } }, - "samples/typescript/01.dice-roller": { - "name": "@microsoft/01.dice-roller-ts", - "version": "1.0.0", - "hasInstallScript": true, - "license": "Microsoft", - "dependencies": { - "@fluidframework/azure-client": "^1.1.1", - "@microsoft/live-share": "1.4.0", - "@microsoft/teams-js": "^2.16.0", - "fluid-framework": "^1.3.6" - }, - "devDependencies": { - "@fluidframework/test-client-utils": "^1.3.6", - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.7", - "buffer": "^6.0.3", - "start-server-and-test": "^2.0.0", - "vite": "^4.0.4" + "samples/typescript/21.react-media-template/node_modules/@esbuild/netbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", + "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" } }, - "samples/typescript/03.live-canvas-demo": { - "name": "@microsoft/03.live-canvas-demo-ts", - "version": "1.0.0", - "hasInstallScript": true, - "license": "SEE LICENSE IN LICENSE", - "dependencies": { - "@fluidframework/azure-client": "^1.1.1", - "@microsoft/live-share": "1.4.0", - "@microsoft/live-share-canvas": "1.4.0", - "@microsoft/teams-js": "^2.16.0", - "fluid-framework": "^1.3.6" - }, - "devDependencies": { - "@fluidframework/test-client-utils": "^1.3.6", - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.7", - "buffer": "^6.0.3", - "start-server-and-test": "^2.0.0", - "vite": "^4.0.4" + "samples/typescript/21.react-media-template/node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", + "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" } }, - "samples/typescript/04.live-share-react": { - "name": "@microsoft/04.live-share-react-sample-ts", - "version": "0.4.0", - "hasInstallScript": true, + "samples/typescript/21.react-media-template/node_modules/@esbuild/openbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", + "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@fluentui/react-components": "^9.18.6", - "@fluentui/react-icons": "^2.0.202", - "@fluentui/react-theme": "^9.1.5", - "@fluidframework/azure-client": "^1.1.1", - "@microsoft/live-share": "1.4.0", - "@microsoft/live-share-canvas": "1.4.0", - "@microsoft/live-share-media": "1.4.0", - "@microsoft/live-share-react": "1.4.0-preview.0", - "@microsoft/teams-js": "^2.16.0", - "fluid-framework": "^1.3.6", - "lodash": "^4.17.21", - "prop-types": "^15.8.1", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-router": "^6.4.2", - "react-router-dom": "^6.4.2", - "use-resize-observer": "^9.1.0", - "uuid": "^9.0.0", - "web-vitals": "^3.1.1" - }, - "devDependencies": { - "@fluidframework/test-client-utils": "^1.3.6", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^13.4.0", - "@testing-library/user-event": "^14.4.3", - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.7", - "@vitejs/plugin-react": "^3.0.1", - "dotenv-cli": "^7.2.1", - "eslint": "^8.41.0", - "eslint-config-prettier": "^8.8.0", - "eslint-plugin-prettier": "^4.2.1", - "prettier": "^2.8.8", - "start-server-and-test": "^2.0.0", - "vite": "^4.0.4" + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" } }, - "samples/typescript/05.dice-roller-turbo": { - "name": "@microsoft/05.dice-roller-turbo-ts", - "version": "1.0.0", - "hasInstallScript": true, - "license": "Microsoft", - "dependencies": { - "@fluidframework/azure-client": "^1.1.1", - "@microsoft/live-share": "1.4.0", - "@microsoft/live-share-turbo": "1.4.0-preview.0", - "@microsoft/teams-js": "^2.16.0", - "fluid-framework": "^1.3.6" - }, - "devDependencies": { - "@fluidframework/test-client-utils": "^1.3.6", - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.7", - "buffer": "^6.0.3", - "start-server-and-test": "^2.0.0", - "vite": "^4.0.4" + "samples/typescript/21.react-media-template/node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", + "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" } }, - "samples/typescript/06.presence-avatars": { - "name": "@microsoft/06.presence-avatars", - "version": "0.4.0", - "hasInstallScript": true, + "samples/typescript/21.react-media-template/node_modules/@esbuild/sunos-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", + "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@fluentui/react-components": "^9.18.6", - "@fluentui/react-icons": "^2.0.202", - "@fluentui/react-theme": "^9.1.5", - "@fluidframework/azure-client": "^1.1.1", - "@microsoft/live-share": "1.4.0", - "@microsoft/live-share-canvas": "1.4.0", - "@microsoft/live-share-media": "1.4.0", - "@microsoft/live-share-react": "1.4.0-preview.0", - "@microsoft/teams-js": "^2.16.0", - "fluid-framework": "^1.3.6", - "lodash": "^4.17.21", - "prop-types": "^15.8.1", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-router": "^6.4.2", - "react-router-dom": "^6.4.2", - "use-resize-observer": "^9.1.0", - "uuid": "^9.0.0", - "web-vitals": "^3.1.1" - }, - "devDependencies": { - "@fluidframework/test-client-utils": "^1.3.6", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^13.4.0", - "@testing-library/user-event": "^14.4.3", - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.7", - "@vitejs/plugin-react": "^3.0.1", - "dotenv-cli": "^7.2.1", - "eslint": "^8.41.0", - "eslint-config-prettier": "^8.8.0", - "eslint-plugin-prettier": "^4.2.1", - "prettier": "^2.8.8", - "start-server-and-test": "^2.0.0", - "vite": "^4.0.4" + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" } }, - "samples/typescript/07.countdown-timer": { - "name": "@microsoft/07.countdown-timer", - "version": "0.4.0", - "hasInstallScript": true, + "samples/typescript/21.react-media-template/node_modules/@esbuild/win32-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", + "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@fluentui/react-components": "^9.18.6", - "@fluentui/react-icons": "^2.0.202", - "@fluentui/react-theme": "^9.1.5", - "@fluidframework/azure-client": "^1.1.1", - "@microsoft/live-share": "1.4.0", - "@microsoft/live-share-canvas": "1.4.0", - "@microsoft/live-share-media": "1.4.0", - "@microsoft/live-share-react": "1.4.0-preview.0", - "@microsoft/teams-js": "^2.16.0", - "fluid-framework": "^1.3.6", - "lodash": "^4.17.21", - "prop-types": "^15.8.1", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-router": "^6.4.2", - "react-router-dom": "^6.4.2", - "use-resize-observer": "^9.1.0", - "uuid": "^9.0.0", - "web-vitals": "^3.1.1" - }, - "devDependencies": { - "@fluidframework/test-client-utils": "^1.3.6", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^13.4.0", - "@testing-library/user-event": "^14.4.3", - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.7", - "@vitejs/plugin-react": "^3.0.1", - "dotenv-cli": "^7.2.1", - "eslint": "^8.41.0", - "eslint-config-prettier": "^8.8.0", - "eslint-plugin-prettier": "^4.2.1", - "prettier": "^2.8.8", - "start-server-and-test": "^2.0.0", - "vite": "^4.0.4" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" } }, - "samples/typescript/08.3d-model": { - "name": "@microsoft/08.3d-model", - "version": "0.4.0", - "hasInstallScript": true, + "samples/typescript/21.react-media-template/node_modules/@esbuild/win32-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", + "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", + "cpu": [ + "ia32" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@babylonjs/core": "^6.21.0", - "@babylonjs/loaders": "^6.21.0", - "@fluentui/react-components": "^9.18.6", - "@fluentui/react-icons": "^2.0.202", - "@fluentui/react-theme": "^9.1.5", - "@fluidframework/azure-client": "^1.1.1", - "@microsoft/live-share": "1.4.0", - "@microsoft/live-share-canvas": "1.4.0", - "@microsoft/live-share-media": "1.4.0", - "@microsoft/live-share-react": "1.4.0-preview.0", - "@microsoft/teams-js": "^2.16.0", - "fluid-framework": "^1.3.6", - "lodash": "^4.17.21", - "prop-types": "^15.8.1", - "react": "^18.2.0", - "react-babylonjs": "^3.1.20", - "react-colorful": "^5.6.1", - "react-dom": "^18.2.0", - "react-router": "^6.4.2", - "react-router-dom": "^6.4.2", - "use-resize-observer": "^9.1.0", - "uuid": "^9.0.0", - "web-vitals": "^3.1.1" - }, - "devDependencies": { - "@fluidframework/test-client-utils": "^1.3.6", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^13.4.0", - "@testing-library/user-event": "^14.4.3", - "@types/babylonjs": "^2.4.1", - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.7", - "@vitejs/plugin-react": "^3.0.1", - "dotenv-cli": "^7.2.1", - "eslint": "^8.41.0", - "eslint-config-prettier": "^8.8.0", - "eslint-plugin-prettier": "^4.2.1", - "prettier": "^2.8.8", - "start-server-and-test": "^2.0.0", - "vite": "^4.0.4" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" } }, - "samples/typescript/21.react-media-template": { - "name": "react-media-template-ts", - "version": "0.4.0", + "samples/typescript/21.react-media-template/node_modules/@esbuild/win32-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", + "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "samples/typescript/21.react-media-template/node_modules/esbuild": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", + "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", + "dev": true, "hasInstallScript": true, "license": "MIT", - "dependencies": { - "@fluentui/react-components": "^9.18.6", - "@fluentui/react-icons": "^2.0.202", - "@fluentui/react-theme": "^9.1.5", - "@fluidframework/azure-client": "^1.1.1", - "@microsoft/live-share": "1.4.0", - "@microsoft/live-share-canvas": "1.4.0", - "@microsoft/live-share-media": "1.4.0", - "@microsoft/teams-js": "^2.16.0", - "fluid-framework": "^1.3.6", - "lodash": "^4.17.21", - "prop-types": "^15.8.1", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-router": "^6.4.2", - "react-router-dom": "^6.4.2", - "use-resize-observer": "^9.1.0", - "uuid": "^9.0.0", - "web-vitals": "^3.1.1" + "bin": { + "esbuild": "bin/esbuild" }, - "devDependencies": { - "@fluidframework/test-client-utils": "^1.3.6", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^13.4.0", - "@testing-library/user-event": "^14.4.3", - "@types/lodash": "^4.14.191", - "@types/react": "^18.0.0", - "@types/react-dom": "^18.0.0", - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.7", - "@vitejs/plugin-react": "^3.0.1", - "dotenv-cli": "^7.2.1", - "esbuild": "^0.17.18", - "eslint": "^8.41.0", - "eslint-config-prettier": "^8.8.0", - "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-react": "^7.32.2", - "eslint-plugin-react-hooks": "^4.6.0", - "start-server-and-test": "^2.0.0", - "vite": "^4.0.4" + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.7", + "@esbuild/android-arm": "0.27.7", + "@esbuild/android-arm64": "0.27.7", + "@esbuild/android-x64": "0.27.7", + "@esbuild/darwin-arm64": "0.27.7", + "@esbuild/darwin-x64": "0.27.7", + "@esbuild/freebsd-arm64": "0.27.7", + "@esbuild/freebsd-x64": "0.27.7", + "@esbuild/linux-arm": "0.27.7", + "@esbuild/linux-arm64": "0.27.7", + "@esbuild/linux-ia32": "0.27.7", + "@esbuild/linux-loong64": "0.27.7", + "@esbuild/linux-mips64el": "0.27.7", + "@esbuild/linux-ppc64": "0.27.7", + "@esbuild/linux-riscv64": "0.27.7", + "@esbuild/linux-s390x": "0.27.7", + "@esbuild/linux-x64": "0.27.7", + "@esbuild/netbsd-arm64": "0.27.7", + "@esbuild/netbsd-x64": "0.27.7", + "@esbuild/openbsd-arm64": "0.27.7", + "@esbuild/openbsd-x64": "0.27.7", + "@esbuild/openharmony-arm64": "0.27.7", + "@esbuild/sunos-x64": "0.27.7", + "@esbuild/win32-arm64": "0.27.7", + "@esbuild/win32-ia32": "0.27.7", + "@esbuild/win32-x64": "0.27.7" } }, "samples/typescript/31.live-canvas-tests": { "name": "live-canvas-tests", "version": "1.0.0", - "hasInstallScript": true, "license": "SEE LICENSE IN LICENSE", "dependencies": { - "@fluidframework/azure-client": "^1.1.1", - "@microsoft/live-share": "1.4.0", - "@microsoft/live-share-canvas": "1.4.0", - "fluid-framework": "^1.3.6" + "@fluidframework/azure-client": ">=2.40 <2.120", + "@microsoft/live-share": "2.0.0-internal.18", + "@microsoft/live-share-canvas": "2.0.0-internal.18", + "fluid-framework": ">=2.40 <2.120" }, "devDependencies": { - "@fluidframework/test-client-utils": "^1.3.6", + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", "buffer": "^6.0.3", - "concurrently": "^5.3.0", "start-server-and-test": "^2.0.0", - "vite": "^4.0.4" + "vite": "^6.1.7" } } } diff --git a/package.json b/package.json index a2183771a..9dba38353 100644 --- a/package.json +++ b/package.json @@ -8,32 +8,37 @@ "packages/live-share-acs", "packages/live-share-canvas", "packages/live-share-media", - "packages/live-share-turbo", "packages/live-share-react", + "internal/test-utils", "samples/javascript/*", "samples/typescript/*" ], "scripts": { - "build": "node workspace-cmd-util.js build packages samples/javascript samples/typescript", - "build:packages": "node workspace-cmd-util.js build packages", - "build:samples": "node workspace-cmd-util.js build samples/javascript samples/typescript", - "build:docs": "typedoc packages/live-share packages/live-share-media packages/live-share-turbo packages/live-share-canvas", - "test:packages": "node workspace-cmd-util.js test packages", - "doctor": "eslint **/src/**/*.{j,t}s{,x} --fix --no-error-on-unmatched-pattern" + "build": "npm run build:packages && npm run build:samples", + "build:packages": "node internal/build-tools/concurrent-packages-build.js", + "build:samples": "npm run build -w=\"samples/javascript\" -w=\"samples/typescript\"", + "doctor": "npm run doctor:src && npm run doctor:json && npm run doctor:prettier", + "doctor:src": "npm run doctor:src:packages && npm run doctor:src:buildtools", + "doctor:src:packages": "eslint **/src/**/*.{j,t}s{,x} --fix", + "doctor:src:buildtools": "eslint internal/build-tools/*.js --fix", + "doctor:json": "eslint **/*.json --fix", + "doctor:prettier": "prettier . --write", + "clean": "npm exec --workspaces -- npx rimraf node_modules && npx rimraf node_modules", + "prepare": "node internal/build-tools/ensure-packages-built.js" }, "author": "", "license": "Microsoft", "devDependencies": { - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.7", - "eslint": "^8.41.0", - "eslint-config-prettier": "^8.8.0", - "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-react": "^7.32.2", - "eslint-plugin-react-hooks": "^4.6.0", - "prettier": "^2.8.8", - "sxh": "^1.0.0", - "typedoc": "^0.24.6", - "typescript": "^5.0.4" + "@types/react": "18.3.28", + "@types/react-dom": "18.3.7", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-react": "^7.34.4", + "eslint-plugin-react-hooks": "^4.6.2", + "prettier": "^3.3.3", + "typescript": "~5.5.3" } } diff --git a/packages/live-share-acs/.nycrc.json b/packages/live-share-acs/.nycrc.json index cc236d58b..ec2ba788b 100644 --- a/packages/live-share-acs/.nycrc.json +++ b/packages/live-share-acs/.nycrc.json @@ -8,4 +8,4 @@ "branches": 90, "functions": 95, "lines": 90 - } \ No newline at end of file +} diff --git a/packages/live-share-acs/LICENSE b/packages/live-share-acs/LICENSE index 59479a141..12ea5b6e7 100644 --- a/packages/live-share-acs/LICENSE +++ b/packages/live-share-acs/LICENSE @@ -1,90 +1,87 @@ -MICROSOFT SOFTWARE LICENSE TERMS +MICROSOFT SOFTWARE LICENSE TERMS -MICROSOFT LIVE SHARE SDK +MICROSOFT LIVE SHARE SDK – PRE-RELEASE VERSION ________________________________________ -Copyright (c) Microsoft Corporation -All rights reserved - -These license terms are an agreement between you and Microsoft Corporation (or one of its affiliates). They apply to the software named above and any Microsoft services or software updates (except to the extent such services or updates are accompanied by new or additional terms, in which case those different terms apply prospectively and do not alter your or Microsoft’s rights relating to pre-updated software or services). IF YOU COMPLY WITH THESE LICENSE TERMS, YOU HAVE THE RIGHTS BELOW. BY USING THE SOFTWARE, YOU ACCEPT THESE TERMS. +These license terms are an agreement between you and Microsoft Corporation (or one of its affiliates). They apply to the software named above and any Microsoft services or software updates (except to the extent such services or updates are accompanied by new or additional terms, in which case those different terms apply prospectively and do not alter your or Microsoft’s rights relating to pre-updated software or services). IF YOU COMPLY WITH THESE LICENSE TERMS, YOU HAVE THE RIGHTS BELOW. BY USING THE SOFTWARE, YOU ACCEPT THESE TERMS. 1. INSTALLATION AND USE RIGHTS. - a) General. You may install and use any number of copies of the software to develop and test your applications, solely for the purpose stated in 1(b) below and otherwise for your internal business purposes. - b) Purpose. The use of this license provided under these terms is specifically limited to developing applications that interact solely within the Microsoft Teams Ecosystem. You may distribute the software according to Section 3 of these terms. - c) Third Party Components. The software may include third party components with separate legal notices or governed by other agreements, as may be described in the ThirdPartyNotices file(s) accompanying the software. - d) Microsoft Terms of Use. Some features of the software provide access to, or rely on, online services. The use of those services (but not the software) is governed by separate terms. This includes the Microsoft APIs Terms of Use which can be found at https://docs.microsoft.com/legal/microsoft-apis/terms-of-use, the Microsoft Developer Agreement which can be found at https://learn.microsoft.com/legal/mdsa, and the Supplemental Terms of Use for Microsoft Azure which can be found at https://azure.microsoft.com/support/legal/preview-supplemental-terms. Please read them. The services may not be available in all regions. - -2. NO WARRANTIES. The software comes with no warranties as provided under Section 13. It may not operate correctly. We may change or discontinue the software at any time without notice. - -3. DISTRIBUTABLE CODE. The software contains code you are permitted to distribute (i.e. make available for third parties) in applications you develop, as described in this Section. - a) Distribution Rights. The code and test files are distributable if included with the software. - i. Third Party Distribution. You may permit distributors of your applications to copy and distribute any of this distributable code you elect to distribute with your applications. - b) Distribution Requirements. For any code you distribute, you must: - i. adhere to the Purpose stated in Section 1(b); and - ii. indemnify, defend, and hold harmless Microsoft from any claims, including attorneys’ fees, related to the distribution or use of your applications, except to the extent that any claim is based solely on the unmodified distributable code. - c) Distribution Restrictions. You may not: - i. use Microsoft’s trademarks or trade dress in your application in any way that suggests your application comes from or is endorsed by Microsoft; or - ii. modify or distribute the source code of any distributable code so that any part of it becomes subject to any license that requires that the distributable code, any other part of the software, or any of Microsoft’s other intellectual property be disclosed or distributed in source code form, or that others have the right to modify it. - -4. SCOPE OF LICENSE. The software is licensed, not sold. Microsoft reserves all other rights. Unless applicable law gives you more rights despite this limitation, you will not (and have no right to): - a) remove, minimize, block, or modify any notices of Microsoft or its suppliers in the software;software; - b) use the software in any way that is against the law or to create or propagate malware; or - c) share, publish, distribute, or lease the software (except for any distributable code, subject to the terms above), provide the software as a stand-alone offering for others to use, or transfer the software or this agreement to any third party. + a) General. You may install and use any number of copies of the software to develop and test your applications, solely for the purpose stated in 1(b) below and otherwise for your internal business purposes. + b) Purpose. The use of this license provided under these terms is specifically limited to developing applications that interact solely within the Microsoft Teams Ecosystem. You may distribute the software according to Section 3 of these terms. + c) Third Party Components. The software may include third party components with separate legal notices or governed by other agreements, as may be described in the ThirdPartyNotices file(s) accompanying the software. + d) Microsoft Terms of Use. Some features of the software provide access to, or rely on, online services. The use of those services (but not the software) is governed by separate terms. This includes the Microsoft APIs Terms of Use which can be found at https://docs.microsoft.com/en-us/legal/microsoft-apis/terms-of-use and the Supplemental Terms of Use for Microsoft Azure which can be found at https://azure.microsoft.com/en-us/support/legal/preview-supplemental-terms. Please read them. The services may not be available in all regions. + +2. PRE-RELEASE SOFTWARE. The software is a pre-release version, and comes with no warranties as provided under Section 13. It may not operate correctly. We may change or discontinue the software at any time without notice. We may also choose not to make this software generally commercially available. It may be different from the commercially released version. + +3. DISTRIBUTABLE CODE. The software contains code you are permitted to distribute (i.e. make available for third parties) in applications you develop, as described in this Section. + a) Distribution Rights. The code and test files are distributable if included with the software. + i. Third Party Distribution. You may permit distributors of your applications to copy and distribute any of this distributable code you elect to distribute with your applications. + b) Distribution Requirements. For any code you distribute, you must: + i. adhere to the Purpose stated in Section 1(b); and + ii. indemnify, defend, and hold harmless Microsoft from any claims, including attorneys’ fees, related to the distribution or use of your applications, except to the extent that any claim is based solely on the unmodified distributable code. + c) Distribution Restrictions. You may not: + i. use Microsoft’s trademarks or trade dress in your application in any way that suggests your application comes from or is endorsed by Microsoft; or + ii. modify or distribute the source code of any distributable code so that any part of it becomes subject to any license that requires that the distributable code, any other part of the software, or any of Microsoft’s other intellectual property be disclosed or distributed in source code form, or that others have the right to modify it. + +4. SCOPE OF LICENSE. The software is licensed, not sold. Microsoft reserves all other rights. Unless applicable law gives you more rights despite this limitation, you will not (and have no right to): + a) remove, minimize, block, or modify any notices of Microsoft or its suppliers in the software;software; + b) use the software in any way that is against the law or to create or propagate malware; or + c) share, publish, distribute, or lease the software (except for any distributable code, subject to the terms above), provide the software as a stand-alone offering for others to use, or transfer the software or this agreement to any third party. 5. Data Protection. There are also some features in the software that may enable you to collect data from users of your applications. If you use these features to enable data collection in your applications, you must comply with applicable law, including providing appropriate notices to and obtaining consent from users of your applications. You can learn more about data collection and use in the help documentation and the privacy statement at https://aka.ms/privacy. Your use of the software operates as your consent to these practices. -6. CODE OF CONDUCT. By agreeing to these license terms, you’re agreeing that, when using the software, you will follow these rules: - a) Don’t do anything illegal. - b) Don’t engage in any activity that exploits, harms, or threatens to harm children. - c) Don’t send spam. Spam is unwanted or unsolicited bulk email, postings, contact requests, SMS (text messages), or instant messages. - d) Don’t publicly display or use the software to share inappropriate content or material (involving, for example, nudity, bestiality, pornography, offensive language, graphic violence, or criminal activity). - e) Don’t engage in activity that is fraudulent, false or misleading (e.g., asking for money under false pretenses, impersonating someone else, manipulating the software to increase play count, or affect rankings, ratings, or comments). - f) Don’t circumvent any restrictions on access to or availability of the software. - g) Don’t engage in activity that is harmful to you, the software, or others (e.g., transmitting viruses, stalking, posting terrorist content, communicating hate speech, or advocating violence against others). - h) Don’t infringe upon the rights of others (e.g., unauthorized sharing of copyrighted music or other copyrighted material, resale or other distribution of Bing maps, or photographs). - i) Don’t engage in activity that violates the privacy of others. - j) Don’t help others break these rules. +6. CODE OF CONDUCT. By agreeing to these license terms, you’re agreeing that, when using the software, you will follow these rules: + a) Don’t do anything illegal. + b) Don’t engage in any activity that exploits, harms, or threatens to harm children. + c) Don’t send spam. Spam is unwanted or unsolicited bulk email, postings, contact requests, SMS (text messages), or instant messages. + d) Don’t publicly display or use the software to share inappropriate content or material (involving, for example, nudity, bestiality, pornography, offensive language, graphic violence, or criminal activity). + e) Don’t engage in activity that is fraudulent, false or misleading (e.g., asking for money under false pretenses, impersonating someone else, manipulating the software to increase play count, or affect rankings, ratings, or comments). + f) Don’t circumvent any restrictions on access to or availability of the software. + g) Don’t engage in activity that is harmful to you, the software, or others (e.g., transmitting viruses, stalking, posting terrorist content, communicating hate speech, or advocating violence against others). + h) Don’t infringe upon the rights of others (e.g., unauthorized sharing of copyrighted music or other copyrighted material, resale or other distribution of Bing maps, or photographs). + i) Don’t engage in activity that violates the privacy of others. + j) Don’t help others break these rules. -7. EXPORT RESTRICTIONS. You must comply with all domestic and international export laws and regulations that apply to the software, which include restrictions on destinations, end users, and end use. For further information on export restrictions, visit https://aka.ms/exporting. +7. EXPORT RESTRICTIONS. You must comply with all domestic and international export laws and regulations that apply to the software, which include restrictions on destinations, end users, and end use. For further information on export restrictions, visit https://aka.ms/exporting. -8. SUPPORT SERVICES. Microsoft is not obligated under this agreement to provide any support services for the software. Any support provided is “as is”, “with all faults”, and without warranty of any kind. +8. SUPPORT SERVICES. Microsoft is not obligated under this agreement to provide any support services for the software. Any support provided is “as is”, “with all faults”, and without warranty of any kind. 9. ENTIRE AGREEMENT. This agreement, terms referenced herein, and any other terms Microsoft may provide for supplements, updates, or third-party applications, is the entire agreement for the software. -10. APPLICABLE LAW AND PLACE TO RESOLVE DISPUTES. If you acquired the software in the United States or Canada, the laws of the state or province where you live (or, if a business, where your principal place of business is located) govern the interpretation of this agreement, claims for its breach, and all other claims (including consumer protection, unfair competition, and tort claims), regardless of conflict of laws principles, except that the FAA governs everything related to arbitration. If you acquired the software in any other country, its laws apply, except that the FAA governs everything related to arbitration. If U.S. federal jurisdiction exists, you and Microsoft consent to exclusive jurisdiction and venue in the federal court in King County, Washington for all disputes heard in court (excluding arbitration). If not, you and Microsoft consent to exclusive jurisdiction and venue in the Superior Court of King County, Washington for all disputes heard in court (excluding arbitration). - -11. CONSUMER RIGHTS; REGIONAL VARIATIONS. This agreement describes certain legal rights. You may have other rights, including consumer rights, under the laws of your state or country. Separate and apart from your relationship with Microsoft, you may also have rights with respect to the party from which you acquired the software. This agreement does not change those other rights if the laws of your state or country do not permit it to do so. For example, if you acquired the software in one of the below regions, or mandatory country law applies, then the following provisions apply to you: - a. Australia. You have statutory guarantees under the Australian Consumer Law and nothing in this agreement is intended to affect those rights. - b. Canada. If you acquired this software in Canada, you may stop receiving updates by turning off the automatic update feature, disconnecting your device from the Internet (if and when you re-connect to the Internet, however, the software will resume checking for and installing updates), or uninstalling the software. The product documentation, if any, may also specify how to turn off updates for your specific device or software. - c. Germany and Austria. - • Warranty. The properly licensed software will perform substantially as described in any Microsoft materials that accompany the software. However, Microsoft gives no contractual guarantee in relation to the licensed software. - • Limitation of Liability. In case of intentional conduct, gross negligence, claims based on the Product Liability Act, as well as, in case of death or personal or physical injury, Microsoft is liable according to the statutory law. - • Subject to the foregoing clause ii., Microsoft will only be liable for slight negligence if Microsoft is in breach of such material contractual obligations, the fulfillment of which facilitate the due performance of this agreement, the breach of which would endanger the purpose of this agreement and the compliance with which a party may constantly trust in (so-called "cardinal obligations"). In other cases of slight negligence, Microsoft will not be liable for slight negligence. - -12. DISCLAIMER OF WARRANTY. THE SOFTWARE IS LICENSED “AS IS.” YOU BEAR THE RISK OF USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES, OR CONDITIONS. TO THE EXTENT PERMITTED UNDER APPLICABLE LAWS, MICROSOFT EXCLUDES ALL IMPLIED WARRANTIES, INCLUDING MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +10. APPLICABLE LAW AND PLACE TO RESOLVE DISPUTES. If you acquired the software in the United States or Canada, the laws of the state or province where you live (or, if a business, where your principal place of business is located) govern the interpretation of this agreement, claims for its breach, and all other claims (including consumer protection, unfair competition, and tort claims), regardless of conflict of laws principles, except that the FAA governs everything related to arbitration. If you acquired the software in any other country, its laws apply, except that the FAA governs everything related to arbitration. If U.S. federal jurisdiction exists, you and Microsoft consent to exclusive jurisdiction and venue in the federal court in King County, Washington for all disputes heard in court (excluding arbitration). If not, you and Microsoft consent to exclusive jurisdiction and venue in the Superior Court of King County, Washington for all disputes heard in court (excluding arbitration). -13. DISCLAIMER. THIS SOFTWARE AND UNDERLYING SERVICES, ARE PROVIDED "AS-IS," "WITH ALL FAULTS," AND "AS AVAILABLE," AND ARE EXCLUDED FROM THE SERVICE LEVEL AGREEMENTS AND LIMITED WARRANTY. This software is not covered by customer support, and may be subject to reduced or different security, compliance and privacy commitments, as further explained in the Microsoft Privacy Statement, Microsoft Azure Trust Center, the Product Terms, the DPA, and any additional notices provided with the software. Where applicable, the following terms in the DPA do not apply to Previews: Processing of Personal Data; GDPR, Data Security. +11. CONSUMER RIGHTS; REGIONAL VARIATIONS. This agreement describes certain legal rights. You may have other rights, including consumer rights, under the laws of your state or country. Separate and apart from your relationship with Microsoft, you may also have rights with respect to the party from which you acquired the software. This agreement does not change those other rights if the laws of your state or country do not permit it to do so. For example, if you acquired the software in one of the below regions, or mandatory country law applies, then the following provisions apply to you: + a. Australia. You have statutory guarantees under the Australian Consumer Law and nothing in this agreement is intended to affect those rights. + b. Canada. If you acquired this software in Canada, you may stop receiving updates by turning off the automatic update feature, disconnecting your device from the Internet (if and when you re-connect to the Internet, however, the software will resume checking for and installing updates), or uninstalling the software. The product documentation, if any, may also specify how to turn off updates for your specific device or software. + c. Germany and Austria. + • Warranty. The properly licensed software will perform substantially as described in any Microsoft materials that accompany the software. However, Microsoft gives no contractual guarantee in relation to the licensed software. + • Limitation of Liability. In case of intentional conduct, gross negligence, claims based on the Product Liability Act, as well as, in case of death or personal or physical injury, Microsoft is liable according to the statutory law. + • Subject to the foregoing clause ii., Microsoft will only be liable for slight negligence if Microsoft is in breach of such material contractual obligations, the fulfillment of which facilitate the due performance of this agreement, the breach of which would endanger the purpose of this agreement and the compliance with which a party may constantly trust in (so-called "cardinal obligations"). In other cases of slight negligence, Microsoft will not be liable for slight negligence. -14. LIMITATION ON AND EXCLUSION OF DAMAGES. IF YOU HAVE ANY BASIS FOR RECOVERING DAMAGES DESPITE THE PRECEDING DISCLAIMER OF WARRANTY, YOU CAN RECOVER FROM MICROSOFT AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT, OR INCIDENTAL DAMAGES. +12. DISCLAIMER OF WARRANTY. THE SOFTWARE IS LICENSED “AS IS.” YOU BEAR THE RISK OF USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES, OR CONDITIONS. TO THE EXTENT PERMITTED UNDER APPLICABLE LAWS, MICROSOFT EXCLUDES ALL IMPLIED WARRANTIES, INCLUDING MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. - This limitation applies to (a) anything related to the software, services, content (including code) on third party Internet sites, or third party applications; and (b) claims for breach of contract, warranty, guarantee, or condition; strict liability, negligence, or other tort; or any other claim; in each case to the extent permitted by applicable law. +13. PRE-RELEASE DISCLAIMER. AS A PRE-RELEASE VERSION, THIS SOFTWARE AND UNDERLYING SERVICES, ARE PROVIDED "AS-IS," "WITH ALL FAULTS," AND "AS AVAILABLE," AND ARE EXCLUDED FROM THE SERVICE LEVEL AGREEMENTS AND LIMITED WARRANTY. Pre-release versions may not be covered by customer support, and may be subject to reduced or different security, compliance and privacy commitments, as further explained in the Microsoft Privacy Statement, Microsoft Azure Trust Center, the Product Terms, the DPA, and any additional notices provided with the software. Where applicable, the following terms in the DPA do not apply to Previews: Processing of Personal Data; GDPR, Data Security. - It also applies even if Microsoft knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your state, province, or country may not allow the exclusion or limitation of incidental, consequential, or other damages. +14. LIMITATION ON AND EXCLUSION OF DAMAGES. IF YOU HAVE ANY BASIS FOR RECOVERING DAMAGES DESPITE THE PRECEDING DISCLAIMER OF WARRANTY, YOU CAN RECOVER FROM MICROSOFT AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT, OR INCIDENTAL DAMAGES. - Please note: As this software is distributed in Canada, some of the clauses in this agreement are provided below in French. + This limitation applies to (a) anything related to the software, services, content (including code) on third party Internet sites, or third party applications; and (b) claims for breach of contract, warranty, guarantee, or condition; strict liability, negligence, or other tort; or any other claim; in each case to the extent permitted by applicable law. + + It also applies even if Microsoft knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your state, province, or country may not allow the exclusion or limitation of incidental, consequential, or other damages. + + Please note: As this software is distributed in Canada, some of the clauses in this agreement are provided below in French. - Remarque: Ce logiciel étant distribué au Canada, certaines des clauses dans ce contrat sont fournies ci-dessous en français. + Remarque: Ce logiciel étant distribué au Canada, certaines des clauses dans ce contrat sont fournies ci-dessous en français. - EXONÉRATION DE GARANTIE. Le logiciel visé par une licence est offert « tel quel ». Toute utilisation de ce logiciel est à votre seule risque et péril. Microsoft n’accorde aucune autre garantie expresse. Vous pouvez bénéficier de droits additionnels en vertu du droit local sur la protection des consommateurs, que ce contrat ne peut modifier. La ou elles sont permises par le droit locale, les garanties implicites de qualité marchande, d’adéquation à un usage particulier et d’absence de contrefaçon sont exclues. + EXONÉRATION DE GARANTIE. Le logiciel visé par une licence est offert « tel quel ». Toute utilisation de ce logiciel est à votre seule risque et péril. Microsoft n’accorde aucune autre garantie expresse. Vous pouvez bénéficier de droits additionnels en vertu du droit local sur la protection des consommateurs, que ce contrat ne peut modifier. La ou elles sont permises par le droit locale, les garanties implicites de qualité marchande, d’adéquation à un usage particulier et d’absence de contrefaçon sont exclues. - LIMITATION DES DOMMAGES-INTÉRÊTS ET EXCLUSION DE RESPONSABILITÉ POUR LES DOMMAGES. Vous pouvez obtenir de Microsoft et de ses fournisseurs une indemnisation en cas de dommages directs uniquement à hauteur de 5,00 $ US. Vous ne pouvez prétendre à aucune indemnisation pour les autres dommages, y compris les dommages spéciaux, indirects ou accessoires et pertes de bénéfices. + LIMITATION DES DOMMAGES-INTÉRÊTS ET EXCLUSION DE RESPONSABILITÉ POUR LES DOMMAGES. Vous pouvez obtenir de Microsoft et de ses fournisseurs une indemnisation en cas de dommages directs uniquement à hauteur de 5,00 $ US. Vous ne pouvez prétendre à aucune indemnisation pour les autres dommages, y compris les dommages spéciaux, indirects ou accessoires et pertes de bénéfices. - Cette limitation concerne: + Cette limitation concerne: - • tout ce qui est relié au logiciel, aux services ou au contenu (y compris le code) figurant sur des sites Internet tiers ou dans des programmes tiers; et + • tout ce qui est relié au logiciel, aux services ou au contenu (y compris le code) figurant sur des sites Internet tiers ou dans des programmes tiers; et - • les réclamations au titre de violation de contrat ou de garantie, ou au titre de responsabilité stricte, de négligence ou d’une autre faute dans la limite autorisée par la loi en vigueur. + • les réclamations au titre de violation de contrat ou de garantie, ou au titre de responsabilité stricte, de négligence ou d’une autre faute dans la limite autorisée par la loi en vigueur. - Elle s’applique également, même si Microsoft connaissait ou devrait connaître l’éventualité d’un tel dommage. Si votre pays n’autorise pas l’exclusion ou la limitation de responsabilité pour les dommages indirects, accessoires ou de quelque nature que ce soit, il se peut que la limitation ou l’exclusion ci-dessus ne s’appliquera pas à votre égard. + Elle s’applique également, même si Microsoft connaissait ou devrait connaître l’éventualité d’un tel dommage. Si votre pays n’autorise pas l’exclusion ou la limitation de responsabilité pour les dommages indirects, accessoires ou de quelque nature que ce soit, il se peut que la limitation ou l’exclusion ci-dessus ne s’appliquera pas à votre égard. - EFFET JURIDIQUE. Le présent contrat décrit certains droits juridiques. Vous pourriez avoir d’autres droits prévus par les lois de votre pays. Le présent contrat ne modifie pas les droits que vous confèrent les lois de votre pays si celles-ci ne le permettent pas. + EFFET JURIDIQUE. Le présent contrat décrit certains droits juridiques. Vous pourriez avoir d’autres droits prévus par les lois de votre pays. Le présent contrat ne modifie pas les droits que vous confèrent les lois de votre pays si celles-ci ne le permettent pas. \ No newline at end of file diff --git a/packages/live-share-acs/README.md b/packages/live-share-acs/README.md index 4cf2df986..18dd178b6 100644 --- a/packages/live-share-acs/README.md +++ b/packages/live-share-acs/README.md @@ -81,7 +81,7 @@ Here's an example of how you can implement this in your application: **JavaScript** ```javascript -import { LiveShareClient, LiveState } from "@microsoft/live-share"; +import { LiveShareClient } from "@microsoft/live-share"; import { ACSTeamsLiveShareHost } from "@microsoft/live-share-acs"; import { app, LiveShareHost } from "@microsoft/teams-js"; import { CallClient } from "@azure/communication-calling"; @@ -89,12 +89,7 @@ import { AzureCommunicationTokenCredential } from "@azure/communication-common"; async function joinSession(host) { const client = new LiveShareClient(host); - const schema = { - initialObjects: { - liveState: LiveState, - }, - }; - const { container } = await client.joinContainer(schema); + const { container } = await client.join(); // ... ready to start app sync logic } @@ -156,7 +151,7 @@ if (IN_TEAMS) { **TypeScript** ```TypeScript -import { LiveShareClient, LiveState, ILiveShareHost } from "@microsoft/live-share"; +import { LiveShareClient, ILiveShareHost } from "@microsoft/live-share"; import { ACSTeamsLiveShareHost } from "@microsoft/live-share-acs"; import { app, LiveShareHost } from "@microsoft/teams-js"; import { CallClient } from "@azure/communication-calling"; @@ -164,12 +159,7 @@ import { AzureCommunicationTokenCredential } from '@azure/communication-common'; async function joinSession(host: ILiveShareHost): Promise { const client = new LiveShareClient(host); - const schema = { - initialObjects: { - liveState: LiveState, - }, - }; - const { container } = await client.joinContainer(schema); + const { container } = await client.join(); // ... ready to start app sync logic } @@ -256,10 +246,10 @@ const longJoinUrl = `https://teams.microsoft.com/l/meetup-join/${threadId}/0?con Integrating Live Share into your app can enhance collaboration between your agents and customers, particularly if your business provides customer services. Here are a few examples of how `ACSTeamsLiveShareHost` can be implemented in your application: -- Facilitate co-browsing of your website between your support agents and customers. -- Enable your retail agents and digital shoppers to co-shop on your e-commerce website. -- Provide onboarding assistance through your sales representatives for new customers. -- Allow co-watching of high-quality promotional videos during sales calls. +- Facilitate co-browsing of your website between your support agents and customers. +- Enable your retail agents and digital shoppers to co-shop on your e-commerce website. +- Provide onboarding assistance through your sales representatives for new customers. +- Allow co-watching of high-quality promotional videos during sales calls. ## Code samples @@ -277,16 +267,17 @@ The Live Share SDK contains dependencies for [@microsoft/teams-js](https://www.n | @microsoft/live-share | @microsoft/teams-js | fluid-framework | @microsoft/live-share-\* | @fluidframework/azure-client | @microsoft/TeamsFx | @microsoft/TeamsFx-react | | --------------------- | ------------------- | --------------- | ------------------------ | ---------------------------- | ------------------ | ------------------------ | +| ^2.0.0 | ^2.11.0 | ^2.0.0 | ^2.0.0 | ^2.0.0 | ^2.5.0 | ^2.5.0 | | ^1.0.0 | ^2.11.0 | ^1.2.3 | ^1.0.0 | ^1.0.0 | ^2.5.0 | ^2.5.0 | ## Contributing There are several ways you can [contribute](../../CONTRIBUTING.md) to this project: -- [Submit bugs](https://github.com/microsoft/live-share-sdk/issues) and help us verify fixes as they are checked in. -- Review the source code changes. -- Engage with other Live Share developers on [StackOverflow](https://stackoverflow.com/questions/tagged/live-share). -- [Contribute bug fixes](../../CONTRIBUTING.md). +- [Submit bugs](https://github.com/microsoft/live-share-sdk/issues) and help us verify fixes as they are checked in. +- Review the source code changes. +- Engage with other Live Share developers on [StackOverflow](https://stackoverflow.com/questions/tagged/live-share). +- [Contribute bug fixes](../../CONTRIBUTING.md). This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact with any additional questions or comments. diff --git a/packages/live-share-acs/package.json b/packages/live-share-acs/package.json index 3dc4f9508..e6b3c04c9 100644 --- a/packages/live-share-acs/package.json +++ b/packages/live-share-acs/package.json @@ -1,31 +1,36 @@ { "name": "@microsoft/live-share-acs", - "version": "1.4.0-preview.5", + "version": "2.0.0-internal.18", "description": "Live Share integration package for Azure Communication Services.", "author": "Microsoft", "license": "SEE LICENSE IN LICENSE", - "main": "./bin/index.js", - "types": "./bin/index.d.ts", + "type": "module", "scripts": { "clean": "npx shx rm -rf bin", - "build": "tsc -p tsconfig.build.json", + "build": "node ../../internal/build-tools/build-package.js --esm", "test": "ts-mocha src/**/*.spec.ts --timeout 10000", "test:debug": "ts-mocha src/**/*.spec.ts --inspect-brk", "test:coverage": "nyc --reporter=html --reporter=text --reporter=text-summary npm test" }, + "exports": { + "./package.json": "./package.json", + ".": { + "import": "./bin/esm/index.js" + } + }, "devDependencies": { - "@microsoft/live-share": "1.4.0", - "@azure/communication-calling": "^1.14.0", + "@microsoft/live-share": "2.0.0-internal.18", + "@azure/communication-calling": "^1.27.3", "@types/assert": "^1.5.6", "@types/mocha": "^10.0.1", - "@types/node": "^18.11.18", + "@types/node": "^20.2.3", "mocha": "^10.2.0", "nyc": "^15.1.0", "ts-mocha": "^10.0.0", - "typescript": "^4.6.4" + "typescript": "~5.5.3" }, "peerDependencies": { - "@microsoft/live-share": "1.4.0", + "@microsoft/live-share": "2.0.0-internal.18", "@azure/communication-calling": "^1.14.0" }, "repository": { diff --git a/packages/live-share-acs/src/ACSTeamsLiveShareHost.ts b/packages/live-share-acs/src/ACSTeamsLiveShareHost.ts index 64a3a402e..66f459157 100644 --- a/packages/live-share-acs/src/ACSTeamsLiveShareHost.ts +++ b/packages/live-share-acs/src/ACSTeamsLiveShareHost.ts @@ -26,7 +26,7 @@ import { isINtpTimeInfo, isIGetClientInfoResponse, isUserMeetingRoleResponse, -} from "./internals"; +} from "./internals/index.js"; const LiveShareRoutePrefix = "livesync/v1/acs"; const LiveShareBaseUrl = "https://teams.microsoft.com/api/platform"; diff --git a/packages/live-share-acs/src/index.ts b/packages/live-share-acs/src/index.ts index 40ddff3c9..1c1955547 100644 --- a/packages/live-share-acs/src/index.ts +++ b/packages/live-share-acs/src/index.ts @@ -1 +1 @@ -export * from "./ACSTeamsLiveShareHost"; +export * from "./ACSTeamsLiveShareHost.js"; diff --git a/packages/live-share-acs/src/internals/index.ts b/packages/live-share-acs/src/internals/index.ts index e2dd4d256..3e4b43e81 100644 --- a/packages/live-share-acs/src/internals/index.ts +++ b/packages/live-share-acs/src/internals/index.ts @@ -1,2 +1,2 @@ -export * from "./interfaces"; -export * from "./type-guards"; +export * from "./interfaces.js"; +export * from "./type-guards.js"; diff --git a/packages/live-share-acs/src/internals/type-guards.ts b/packages/live-share-acs/src/internals/type-guards.ts index 7e08b4ce5..0f1ba25e5 100644 --- a/packages/live-share-acs/src/internals/type-guards.ts +++ b/packages/live-share-acs/src/internals/type-guards.ts @@ -12,7 +12,7 @@ import { IFluidTenantInfoResponse, IFluidTokenResponse, IGetClientInfoResponse, -} from "./interfaces"; +} from "./interfaces.js"; /** * @hidden diff --git a/packages/live-share-acs/tsconfig.build.json b/packages/live-share-acs/tsconfig.build.json deleted file mode 100644 index 9d8cab4a6..000000000 --- a/packages/live-share-acs/tsconfig.build.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ - }, - "exclude": [ - "test/**/*.ts" - ] - } \ No newline at end of file diff --git a/packages/live-share-acs/tsconfig.json b/packages/live-share-acs/tsconfig.json index 9d500ddde..f1195380b 100644 --- a/packages/live-share-acs/tsconfig.json +++ b/packages/live-share-acs/tsconfig.json @@ -1,76 +1,66 @@ { - "compilerOptions": { - /* Visit https://aka.ms/tsconfig.json to read more about this file */ - - /* Basic Options */ - // "incremental": true, /* Enable incremental compilation */ - "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ - "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ - "lib": ["es2020","DOM"], /* Specify library files to be included in the compilation. */ - "allowJs": false, /* Allow javascript files to be compiled. */ - // "checkJs": true, /* Report errors in .js files. */ - // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ - "declaration": true, /* Generates corresponding '.d.ts' file. */ - "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ - "sourceMap": true, /* Generates corresponding '.map' file. */ - // "outFile": "./", /* Concatenate and emit output to single file. */ - "outDir": "./bin", /* Redirect output structure to the directory. */ - // "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ - // "composite": true, /* Enable project compilation */ - // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ - // "removeComments": true, /* Do not emit comments to output. */ - // "noEmit": true, /* Do not emit outputs. */ - // "importHelpers": true, /* Import emit helpers from 'tslib'. */ - // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ - // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ - - /* Strict Type-Checking Options */ - "strict": true, /* Enable all strict type-checking options. */ - // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* Enable strict null checks. */ - // "strictFunctionTypes": true, /* Enable strict checking of function types. */ - // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ - // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ - // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ - // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ - - /* Additional Checks */ - // "noUnusedLocals": true, /* Report errors on unused locals. */ - // "noUnusedParameters": true, /* Report errors on unused parameters. */ - // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ - // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - - /* Module Resolution Options */ - // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ - // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ - // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ - // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ - // "typeRoots": [], /* List of folders to include type definitions from. */ - // "types": [], /* Type declaration files to be included in compilation. */ - // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ - "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ - // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - - /* Source Map Options */ - // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ - // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ - - /* Experimental Options */ - // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ - // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ - - /* Advanced Options */ - "skipLibCheck": true, /* Skip type checking of declaration files. */ - "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ - }, - "exclude": ["build", "dist", "node_modules"], - "include": [ - "test/**/*.ts" - ], - "files": [ - "src/index.ts" - ] + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + /* Basic Options */ + // "incremental": true, /* Enable incremental compilation */ + "target": "ES2022" /* Specify ECMAScript target version. */, + "module": "Node16" /* Specify module code generation. */, + "lib": [ + "ES2022", + "DOM" + ] /* Specify library files to be included in the compilation. */, + "allowJs": false /* Allow javascript files to be compiled. */, + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + "declaration": true /* Generates corresponding '.d.ts' file. */, + "declarationMap": true /* Generates a sourcemap for each corresponding '.d.ts' file. */, + "sourceMap": true /* Generates corresponding '.map' file. */, + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "./bin/esm" /* Redirect output structure to the directory. */, + // "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + /* Strict Type-Checking Options */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + /* Module Resolution Options */ + // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + /* Advanced Options */ + "skipLibCheck": true /* Skip type checking of declaration files. */, + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + }, + "files": ["src/index.ts"] } diff --git a/packages/live-share-acs/typedoc.json b/packages/live-share-acs/typedoc.json deleted file mode 100644 index 10851b2ed..000000000 --- a/packages/live-share-acs/typedoc.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "entryPoints": ["./src/index.ts"], - "excludeExternals": true, - "excludePrivate": true, - "excludeInternal": true, - "name": "_microsoft_live_share_media", - "validation": { - "invalidLink": true - } -} diff --git a/packages/live-share-canvas/.nycrc.json b/packages/live-share-canvas/.nycrc.json index cc236d58b..ec2ba788b 100644 --- a/packages/live-share-canvas/.nycrc.json +++ b/packages/live-share-canvas/.nycrc.json @@ -8,4 +8,4 @@ "branches": 90, "functions": 95, "lines": 90 - } \ No newline at end of file +} diff --git a/packages/live-share-canvas/README.md b/packages/live-share-canvas/README.md index e77cda0d5..114c1e360 100644 --- a/packages/live-share-canvas/README.md +++ b/packages/live-share-canvas/README.md @@ -36,27 +36,26 @@ This will use npm workspaces to hoist and build all dependencies. ```html -
        +
        ``` ```javascript import { LiveShareHost } from "@microsoft/teams-js"; import { LiveShareClient } from "@microsoft/live-share"; -import { LiveCanvas, InkingManager, InkingTool } from "@microsoft/live-share-canvas"; +import { + LiveCanvas, + InkingManager, + InkingTool, +} from "@microsoft/live-share-canvas"; -// Setup the Fluid container +// Setup the Client const host = LiveShareHost.create(); const client = new LiveShareClient(host); -const containerSchema = { - initialObjects: { - // Include a LiveCanvas in your container schema - liveCanvas: LiveCancas, - ... - } -}; - -const { container } = await client.joinContainer(containerSchema); +await client.join(); const inkingHost = document.getElementById("inkingHost"); @@ -65,7 +64,8 @@ const inkingManager = new InkingManager(inkingHost); // Initialize the LiveCanvas, which will synchronize the events and // drawing generated by the InkingManager passed as a parameter -const liveCanvas = container.initialObjects.liveCanvas as LiveCanvas; +const liveCanvas = + (await client.getDDS) < LiveCanvas > ("canvas-id", LiveCanvas); await liveCanvas.initialize(inkingManager); // Activate the InkingManager so it starts handling pointer input @@ -74,15 +74,15 @@ inkingManager.activate(); // You can then select tools and setup brushes via the InkingManager instance document.getElementById("btnPen").onclick = () => { inkingManager.tool = InkingTool.Pen; -} +}; document.getElementById("btnLaserPointer").onclick = () => { inkingManager.tool = InkingTool.LaserPointer; -} +}; document.getElementById("btnPenBrushBlue").onclick = () => { - inkingManager.penBrush.color = { r: 0, g: 0, b: 255, a: 1}; -} + inkingManager.penBrush.color = { r: 0, g: 0, b: 255, a: 1 }; +}; // Other tools and brush settings are available, please refer to the documentation at https://aka.ms/livesharecanvas ``` @@ -91,8 +91,8 @@ document.getElementById("btnPenBrushBlue").onclick = () => { A code sample is available in a seperate GitHub repository. -| Sample name | Description | Javascript | -| -- | -- | -- | +| Sample name | Description | Javascript | +| ---------------- | ------------------------------------------------ | ------------------------------------------ | | Live Inking Demo | Basic example showing how to use the LiveCanvas. | How does this work? What link to put here? | ## Package Compatibility @@ -101,9 +101,10 @@ The Live Share SDK contains dependencies for [@microsoft/teams-js](https://www.n **It is critical that your app uses the package dependencies listed in the table below.** Lookup the version of the `@microsoft/live-share` you're using and set any other dependencies in your `package.json` file to match: -| @microsoft/live-share | @microsoft/teams-js | fluid-framework | @microsoft/live-share-\* | @fluidframework/azure-client | @microsoft/TeamsFx | @microsoft/TeamsFx-react | -| --------------------- | -------------------- | --------------- | -------------------------- | ---------------------------- | ------------------------------- | ------------------------------- | -| ^1.0.0 | ^2.11.0 | ^1.2.3 | ^1.0.0 | ^1.0.0 | ^2.5.0 | ^2.5.0 | +| @microsoft/live-share | @microsoft/teams-js | fluid-framework | @microsoft/live-share-\* | @fluidframework/azure-client | @microsoft/TeamsFx | @microsoft/TeamsFx-react | +| --------------------- | ------------------- | --------------- | ------------------------ | ---------------------------- | ------------------ | ------------------------ | +| ^2.0.0 | ^2.11.0 | ^2.0.0 | ^2.0.0 | ^2.0.0 | ^2.5.0 | ^2.5.0 | +| ^1.0.0 | ^2.11.0 | ^1.2.3 | ^1.0.0 | ^1.0.0 | ^2.5.0 | ^2.5.0 | ## Contributing diff --git a/packages/live-share-canvas/package.json b/packages/live-share-canvas/package.json index 514dba7ea..f0083000d 100644 --- a/packages/live-share-canvas/package.json +++ b/packages/live-share-canvas/package.json @@ -1,32 +1,38 @@ { "name": "@microsoft/live-share-canvas", - "version": "1.4.0", + "version": "2.0.0-internal.18", "description": "Live Share extension library for collaborative inking.", "author": "Microsoft", "license": "SEE LICENSE IN LICENSE", - "main": "./bin/index.js", - "types": "./bin/index.d.ts", + "type": "module", "scripts": { "clean": "npx shx rm -rf bin", - "build": "tsc -p tsconfig.build.json", - "test": "ts-mocha src/**/*.spec.ts --timeout 10000", - "test:debug": "ts-mocha src/**/*.spec.ts --inspect-brk", + "build": "node ../../internal/build-tools/build-package.js --esm", + "build:test": "node ../../internal/build-tools/build-package.js --test", + "test": "npm run build:test && mocha --recursive \"./bin/test/**/*.spec.js\" --timeout 10000", + "test:debug": "npm run build:test && mocha --recursive \"./bin/test/**/*.spec.js\" --inspect-brk", "test:coverage": "nyc --reporter=html --reporter=text --reporter=text-summary npm test" }, + "exports": { + "./package.json": "./package.json", + ".": { + "import": "./bin/esm/index.js" + } + }, "devDependencies": { - "@microsoft/live-share": "1.4.0", + "@microsoft/live-share": "2.0.0-internal.18", "@types/assert": "^1.5.6", "@types/mocha": "^10.0.1", "@types/node": "^20.2.3", - "fluid-framework": "^1.3.6", + "fluid-framework": ">=2.40 <2.120", "mocha": "^10.2.0", "nyc": "^15.1.0", "ts-mocha": "^10.0.0", - "typescript": "^5.0.4" + "typescript": "~5.5.3" }, "peerDependencies": { - "@microsoft/live-share": "1.4.0", - "fluid-framework": "^1.2.3" + "@microsoft/live-share": "2.0.0-internal.18", + "fluid-framework": ">=2.40 <2.120" }, "repository": { "directory": "packages/live-share-canvas", diff --git a/packages/live-share-canvas/src/canvas/DryWetCanvas.ts b/packages/live-share-canvas/src/canvas/DryWetCanvas.ts index 46f72ec48..57f383beb 100644 --- a/packages/live-share-canvas/src/canvas/DryWetCanvas.ts +++ b/packages/live-share-canvas/src/canvas/DryWetCanvas.ts @@ -3,14 +3,14 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { InkingCanvas } from "./InkingCanvas"; +import { InkingCanvas } from "./InkingCanvas.js"; import { IPointerPoint, DefaultPenBrush, IBrush, toCssRgbaColor, -} from "../core"; -import { computeQuadPath, IQuadPathSegment } from "../core/internals"; +} from "../core/index.js"; +import { computeQuadPath, IQuadPathSegment } from "../core/internals/index.js"; /** * Represents the base class from wet and dry canvases, implementing the common rendering logic. diff --git a/packages/live-share-canvas/src/canvas/InkingCanvas.ts b/packages/live-share-canvas/src/canvas/InkingCanvas.ts index b6155df53..c4b9ce980 100644 --- a/packages/live-share-canvas/src/canvas/InkingCanvas.ts +++ b/packages/live-share-canvas/src/canvas/InkingCanvas.ts @@ -9,8 +9,8 @@ import { viewportToScreen, IStroke, IBrush, -} from "../core"; -import { IQuad, TWO_PI } from "../core/internals"; +} from "../core/index.js"; +import { IQuad, TWO_PI } from "../core/internals/index.js"; /** * Defines the refernece point of a canvas. The reference point is the origin used for diff --git a/packages/live-share-canvas/src/canvas/LaserPointerCanvas.ts b/packages/live-share-canvas/src/canvas/LaserPointerCanvas.ts index 360b10cca..7ad0eb665 100644 --- a/packages/live-share-canvas/src/canvas/LaserPointerCanvas.ts +++ b/packages/live-share-canvas/src/canvas/LaserPointerCanvas.ts @@ -3,8 +3,8 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { IPointerPoint } from "../core"; -import { WetCanvas } from "./DryWetCanvas"; +import { IPointerPoint } from "../core/index.js"; +import { WetCanvas } from "./DryWetCanvas.js"; /** * Represents a canvas that implements the laser pointer behavior. diff --git a/packages/live-share-canvas/src/canvas/index.ts b/packages/live-share-canvas/src/canvas/index.ts index 7a028032e..d7f12a340 100644 --- a/packages/live-share-canvas/src/canvas/index.ts +++ b/packages/live-share-canvas/src/canvas/index.ts @@ -3,6 +3,6 @@ * Licensed under the Microsoft Live Share SDK License. */ -export * from "./DryWetCanvas"; -export * from "./InkingCanvas"; -export * from "./LaserPointerCanvas"; +export * from "./DryWetCanvas.js"; +export * from "./InkingCanvas.js"; +export * from "./LaserPointerCanvas.js"; diff --git a/packages/live-share-canvas/src/core/Brush.ts b/packages/live-share-canvas/src/core/Brush.ts index 44406723e..60be0696d 100644 --- a/packages/live-share-canvas/src/core/Brush.ts +++ b/packages/live-share-canvas/src/core/Brush.ts @@ -3,7 +3,7 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { BasicColors, HighlighterColors, IColor, PenColors } from "./Colors"; +import { BasicColors, HighlighterColors, IColor, PenColors } from "./Colors.js"; /** * Defines the shape of a brush's tip. diff --git a/packages/live-share-canvas/src/core/Colors.ts b/packages/live-share-canvas/src/core/Colors.ts index f91f874f1..b0a0562d0 100644 --- a/packages/live-share-canvas/src/core/Colors.ts +++ b/packages/live-share-canvas/src/core/Colors.ts @@ -3,7 +3,7 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { forceIntoRange } from "./internals"; +import { forceIntoRange } from "./internals/index.js"; /** * Defines an RGB color diff --git a/packages/live-share-canvas/src/core/InkingManager-constants.ts b/packages/live-share-canvas/src/core/InkingManager-constants.ts new file mode 100644 index 000000000..26f71f0fc --- /dev/null +++ b/packages/live-share-canvas/src/core/InkingManager-constants.ts @@ -0,0 +1,48 @@ +/** + * Defines available inking tools. + */ +export enum InkingTool { + pen = 0, + laserPointer = 1, + highlighter = 2, + eraser = 3, + pointEraser = 4, + line = 5, +} + +/** + * The event emitted by InkingManager when the canvas is cleared. + */ +export const ClearEvent = "Clear"; +/** + * The event emitted by InkingManager when a stroked is added. + */ +export const StrokesAddedEvent = "StrokesAdded"; +/** + * The event emitted by InkingManager when a stroked is removed. + */ +export const StrokesRemovedEvent = "StrokesRemoved"; + +/** + * The event emitted by InkingManager when the pointer moves over the canvas. + */ +export const PointerMovedEvent = "PointerMoved"; + +/** + * The event emitted by InkingManager when a stroke begins. + */ +export const BeginStrokeEvent = "BeginStroke"; + +/** + * Why the stroke state ended + */ +export enum StrokeEndState { + ended, + cancelled, +} + +/** + * The event emitted by InkingManager when points are added to + * the current stroke. + */ +export const AddPointsEvent = "AddPoints"; diff --git a/packages/live-share-canvas/src/core/InkingManager-interfaces.ts b/packages/live-share-canvas/src/core/InkingManager-interfaces.ts new file mode 100644 index 000000000..ebf4f7449 --- /dev/null +++ b/packages/live-share-canvas/src/core/InkingManager-interfaces.ts @@ -0,0 +1,103 @@ +import { IBrush } from "./Brush.js"; +import { IPoint, IPointerPoint } from "./Geometry.js"; +import { StrokeEndState } from "./InkingManager-constants.js"; +import { IStroke, StrokeMode, StrokeType } from "./Stroke.js"; + +/** + * Defines the arguments of the PointerMovedEvent. + */ +export interface IPointerMovedEventArgs { + position?: IPoint; +} + +/** + * Defines the arguments of the BeginStrokeEvent. + */ +export interface IBeginStrokeEventArgs { + /** + * The id of the new stroke. + */ + strokeId: string; + /** + * The type of the new stroke. + */ + type: StrokeType; + /** + * The stroke's mode. + */ + mode: StrokeMode; + /** + * The brush of the new stroke. + */ + brush: IBrush; + /** + * The starting point of the new stroke. + */ + startPoint: IPointerPoint; +} + +/** + * Defines the arguments of the AddPointsEvent. + */ +export interface IAddPointsEventArgs { + /** + * The id of the stroke a point has been added to. + */ + strokeId: string; + /** + * The points that were added to the stroke. + */ + points: IPointerPoint[]; + /** + * Indicates whether the stroke has ended (i.e. if the points + * were the last ones.) + */ + endState?: StrokeEndState; +} + +/** + * Defines a "wet" stroke, i.e. a stroke as it's being drawn. + */ +export interface IWetStroke extends IStroke { + /** + * The type of the wet stroke. + */ + readonly type: StrokeType; + /** + * The wet stroke's mode. + */ + readonly mode: StrokeMode; + /** + * Straightens a point so that the line it forms with the previous + * point is straight (either horizontal or vertical). + * @param p The point to update + */ + straighten(p: IPointerPoint): IPointerPoint; + /** + * Ends the wet stroke. + * @param p Optional. The points at which the stroke ends. If not specified, + * the stroke ends at the last added point. + */ + end(): void; + /** + * Cancels the wet stroke. + */ + cancel(): void; +} + +/** + * Defines options used by `InkingManager.addStroke` and `InkingManager.removeStroke`. + */ +export interface IAddRemoveStrokeOptions { + /** + * Optional. Indicates if the canvas must be fully re-rendered at once after the + * stroke has been added or removed. Defaults to `false`. + */ + forceReRender?: boolean; + /** + * Optional. Indicates whether the add or remove operation should be added to the + * change log, which in turn will lead to `StrokeAddedEvent` or `StrokeRemovedEvent` + * begin emitted. Defaults to `true`. + */ + addToChangeLog?: boolean; +} diff --git a/packages/live-share-canvas/src/core/InkingManager.ts b/packages/live-share-canvas/src/core/InkingManager.ts index 0a576c90b..67e595da9 100644 --- a/packages/live-share-canvas/src/core/InkingManager.ts +++ b/packages/live-share-canvas/src/core/InkingManager.ts @@ -3,14 +3,14 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { EventEmitter } from "events"; +import { TypedEventEmitter } from "@fluid-internal/client-utils"; import { CanvasReferencePoint, InkingCanvas, DryCanvas, WetCanvas, LaserPointerCanvas, -} from "../canvas"; +} from "../canvas/index.js"; import { IPoint, IPointerPoint, @@ -18,7 +18,7 @@ import { screenToViewport, combineRects, viewportToScreen, -} from "./Geometry"; +} from "./Geometry.js"; import { Stroke, IStroke, @@ -26,7 +26,7 @@ import { StrokeType, StrokeMode, IRawStroke, -} from "./Stroke"; +} from "./Stroke.js"; import { InputFilter, InputFilterCollection, @@ -35,34 +35,44 @@ import { InputProvider, PointerInputProvider, IPointerMoveEvent, -} from "../input"; +} from "../input/index.js"; import { DefaultHighlighterBrush, DefaultLaserPointerBrush, DefaultLineBrush, DefaultPenBrush, IBrush, -} from "./Brush"; +} from "./Brush.js"; import { makeRectangle, generateUniqueId, - computeEndArrow, isPointInsideRectangle, computeQuadPath, renderQuadPathToSVG, -} from "./internals"; - -/** - * Defines available inking tools. - */ -export enum InkingTool { - pen = 0, - laserPointer = 1, - highlighter = 2, - eraser = 3, - pointEraser = 4, - line = 5, -} + ChangeLog, + EphemeralCanvas, + WetLineStroke, + WetStroke, + WetFreehandStroke, +} from "./internals/index.js"; +import { IEvent } from "@fluidframework/core-interfaces"; +import { + AddPointsEvent, + BeginStrokeEvent, + ClearEvent, + InkingTool, + PointerMovedEvent, + StrokeEndState, + StrokesAddedEvent, + StrokesRemovedEvent, +} from "./InkingManager-constants.js"; +import { + IAddPointsEventArgs, + IAddRemoveStrokeOptions, + IBeginStrokeEventArgs, + IPointerMovedEventArgs, + IWetStroke, +} from "./InkingManager-interfaces.js"; type StrokeBasedTool = | InkingTool.pen @@ -71,351 +81,64 @@ type StrokeBasedTool = | InkingTool.highlighter; /** - * The event emitted by InkingManager when the canvas is cleared. - */ -export const ClearEvent = "Clear"; -/** - * The event emitted by InkingManager when a stroked is added. - */ -export const StrokesAddedEvent = "StrokesAdded"; -/** - * The event emitted by InkingManager when a stroked is removed. - */ -export const StrokesRemovedEvent = "StrokesRemoved"; - -/** - * Defines the arguments of the PointerMovedEvent. - */ -export interface IPointerMovedEventArgs { - position?: IPoint; -} - -/** - * The event emitted by InkingManager when the pointer moves over the canvas. - */ -export const PointerMovedEvent = "PointerMoved"; - -/** - * Defines the arguments of the BeginStrokeEvent. + * Events emitted by the `InkingManager` class. */ -export interface IBeginStrokeEventArgs { +export interface IInkingManagerEvents extends IEvent { /** - * The id of the new stroke. + * Event listener for when the user's pointer is moved over the canvas element + * @param event update + * @param listener listener function + * @param listener.event the `IPointerMovedEventArgs` event */ - strokeId: string; + ( + event: "PointerMoved", + listener: (event: IPointerMovedEventArgs) => void + ): void; /** - * The type of the new stroke. + * Event listener for when strokes are added to the canvas element + * @param event update + * @param listener listener function + * @param listener.strokes list of strokes that were added */ - type: StrokeType; + (event: "StrokesAdded", listener: (strokes: IStroke[]) => void): void; /** - * The stroke's mode. + * Event listener for when strokes are removed from the canvas element + * @param event update + * @param listener listener function + * @param listener.strokeIds list of stroke ids that were removed */ - mode: StrokeMode; + (event: "StrokesRemoved", listener: (strokeIds: string[]) => void): void; /** - * The brush of the new stroke. + * Event listener for when all strokes are cleared from the canvas element. + * @see InkingManager.clear + * @param event update + * @param listener listener function */ - brush: IBrush; + (event: "Clear", listener: () => void): void; /** - * The starting point of the new stroke. + * Event listener for when a stroke begins. + * @param event update + * @param listener listener function + * @param listener.event event object with information about the stroke that begun */ - startPoint: IPointerPoint; -} - -/** - * The event emitted by InkingManager when a stroke begins. - */ -export const BeginStrokeEvent = "BeginStroke"; - -export enum StrokeEndState { - ended, - cancelled, -} - -/** - * Defines the arguments of the AddPointsEvent. - */ -export interface IAddPointsEventArgs { - /** - * The id of the stroke a point has been added to. - */ - strokeId: string; - /** - * The points that were added to the stroke. - */ - points: IPointerPoint[]; + ( + event: "BeginStroke", + listener: (event: IBeginStrokeEventArgs) => void + ): void; /** - * Indicates whether the stroke has ended (i.e. if the points - * were the last ones.) + * Event listener for when points are added to a stroke. + * Also called when the stroke ends. + * @param event update + * @param listener listener function + * @param listener.event event object with information about the added points */ - endState?: StrokeEndState; -} - -/** - * The event emitted by InkingManager when points are added to - * the current stroke. - */ -export const AddPointsEvent = "AddPoints"; - -/** - * Defines a "wet" stroke, i.e. a stroke as it's being drawn. - */ -export interface IWetStroke extends IStroke { - /** - * The type of the wet stroke. - */ - readonly type: StrokeType; - /** - * The wet stroke's mode. - */ - readonly mode: StrokeMode; - /** - * Straightens a point so that the line it forms with the previous - * point is straight (either horizontal or vertical). - * @param p The point to update - */ - straighten(p: IPointerPoint): IPointerPoint; - /** - * Ends the wet stroke. - * @param p Optional. The points at which the stroke ends. If not specified, - * the stroke ends at the last added point. - */ - end(): void; - /** - * Cancels the wet stroke. - */ - cancel(): void; -} - -class ChangeLog { - private _addedStrokes: Map = new Map(); - private _removedStrokes: Set = new Set(); - - public clear() { - this._addedStrokes.clear(); - this._removedStrokes.clear(); - } - - public mergeChanges(changes: ChangeLog) { - for (let id of changes._removedStrokes) { - if (!this._addedStrokes.delete(id)) { - this._removedStrokes.add(id); - } - } - - changes._addedStrokes.forEach((value: IStroke) => { - this._addedStrokes.set(value.id, value); - }); - } - - public addStroke(stroke: IStroke) { - this._addedStrokes.set(stroke.id, stroke); - } - - public removeStroke(id: string) { - this._removedStrokes.add(id); - } - - public getRemovedStrokes(): string[] { - return [...this._removedStrokes]; - } - - public getAddedStrokes(): IStroke[] { - return [...this._addedStrokes.values()]; - } - - get hasChanges(): boolean { - return this._addedStrokes.size > 0 || this._removedStrokes.size > 0; - } -} - -class EphemeralCanvas extends DryCanvas { - private _removalTimeout?: number; - - constructor(readonly clientId: string, parentElement?: HTMLElement) { - super(parentElement); - } - - scheduleRemoval(onRemoveCallback: (canvas: EphemeralCanvas) => void) { - if (this._removalTimeout) { - window.clearTimeout(this._removalTimeout); - } - - this._removalTimeout = window.setTimeout(() => { - this.fadeOut(); - - onRemoveCallback(this); - }, InkingManager.ephemeralCanvasRemovalDelay); - } -} - -/** - * Defines options used by `InkingManager.addStroke` and `InkingManager.removeStroke`. - */ -export interface IAddRemoveStrokeOptions { - /** - * Optional. Indicates if the canvas must be fully re-rendered at once after the - * stroke has been added or removed. Defaults to `false`. - */ - forceReRender?: boolean; - /** - * Optional. Indicates whether the add or remove operation should be added to the - * change log, which in turn will lead to `StrokeAddedEvent` or `StrokeRemovedEvent` - * begin emitted. Defaults to `true`. - */ - addToChangeLog?: boolean; -} - -abstract class WetStroke extends Stroke implements IWetStroke { - protected notifyStrokeEnded(isCancelled: boolean) { - if (this.onStrokeEnded) { - this.onStrokeEnded(this, isCancelled); - } - } - - onStrokeEnded?: (sender: WetStroke, isCancelled: boolean) => void; - - constructor( - private _canvas: InkingCanvas, - readonly type: StrokeType, - readonly mode: StrokeMode, - options?: IStrokeCreationOptions - ) { - super(options); - - this._canvas.setBrush(this.brush); - } - - straighten(p: IPointerPoint): IPointerPoint { - return p; - } - - end() { - this._canvas.removeFromDOM(); - this._canvas.endStroke(); - - this.notifyStrokeEnded(false); - } - - cancel() { - this._canvas.removeFromDOM(); - this._canvas.cancelStroke(); - - this.notifyStrokeEnded(true); - } - - get canvas(): InkingCanvas { - return this._canvas; - } -} - -class WetFreehandStroke extends WetStroke { - addPoints(...points: IPointerPoint[]): boolean { - const currentLength = this.length; - const result = super.addPoints(...points); - - if (result) { - let startIndex = currentLength; - - if (startIndex === 0) { - this.canvas.beginStroke(this.getPointAt(0)); - - startIndex = 1; - } - - for (let i = startIndex; i < this.length; i++) { - this.canvas.addPoint(this.getPointAt(i)); - } - } - - return result; - } - - end() { - if (this.length > 1 && this.brush.endArrow === "open") { - const penultimatePoint = this.getPointAt(this.length - 2); - const lastPoint = this.getPointAt(this.length - 1); - - const arrowPath = computeEndArrow(penultimatePoint, lastPoint); - - for (let i = 0; i < arrowPath.length; i++) { - const p = { ...arrowPath[i], pressure: lastPoint.pressure }; - - this.addPoint(p); - } - } - - super.end(); - } -} - -class WetLineStroke extends WetStroke { - straighten(p: IPointerPoint): IPointerPoint { - const result = { ...p }; - - if (this.length > 0) { - const firstPoint = this.getPointAt(0); - - if ( - Math.abs(result.x - firstPoint.x) > - Math.abs(result.y - firstPoint.y) - ) { - result.y = firstPoint.y; - } else { - result.x = firstPoint.x; - } - } - - return result; - } - - addPoints(...points: IPointerPoint[]): boolean { - if (this.length === 0) { - this.addPoint(points[0]); - - if (points.length > 1) { - this.addPoint(points[points.length - 1]); - } - } else { - const firstPoint = this.getPointAt(0); - - this.clear(); - - this.addPoint(firstPoint); - this.addPoint(points[points.length - 1]); - } - - this.canvas.cancelStroke(); - this.canvas.beginStroke(this.getPointAt(0)); - - if (this.length > 1) { - this.canvas.addPoint(this.getPointAt(1)); - - if (this.brush.endArrow === "open") { - const arrowPath = computeEndArrow( - this.getPointAt(0), - this.getPointAt(1) - ); - - for (let i = 0; i < arrowPath.length; i++) { - const p = { - ...arrowPath[i], - pressure: this.getPointAt(1).pressure, - }; - - this.addPoint(p); - this.canvas.addPoint(p); - } - } - } - - return true; - } + (event: "AddPoints", listener: (event: IAddPointsEventArgs) => void): void; } /** * Handles user interaction with a canvas, and manages the rendering of wet and dry strokes. */ -export class InkingManager extends EventEmitter { +export class InkingManager extends TypedEventEmitter { /** * Configures the amount of time to wait before sending a pointer moved event. This delay * allows for the elimination of fast, consecutive pointer move events, and only send the @@ -530,7 +253,7 @@ export class InkingManager extends EventEmitter { this._dryCanvas.offset = this._offset; this._dryCanvas.scale = this._scale; - const sortedStrokes = [...this._strokes.values()].sort( + const sortedStrokes = Array.from(this._strokes.values()).sort( (stroke1: IStroke, stroke2: IStroke) => { return stroke1.timeStamp - stroke2.timeStamp; } @@ -561,8 +284,8 @@ export class InkingManager extends EventEmitter { } if (this._changeLog.hasChanges) { - this.notifyStrokesRemoved(...this._changeLog.getRemovedStrokes()); - this.notifyStrokesAdded(...this._changeLog.getAddedStrokes()); + this.notifyStrokesRemoved(this._changeLog.getRemovedStrokes()); + this.notifyStrokesAdded(this._changeLog.getAddedStrokes()); this._changeLog.clear(); } @@ -638,8 +361,8 @@ export class InkingManager extends EventEmitter { this.tool === InkingTool.line ? StrokeMode.line : e.ctrlKey && InkingManager.enableStrokeModifierHotKeys - ? StrokeMode.line - : StrokeMode.freeHand; + ? StrokeMode.line + : StrokeMode.freeHand; // eslint-disable-next-line no-case-declarations const brush = { ...this.getBrushForTool(this.tool) }; @@ -776,8 +499,8 @@ export class InkingManager extends EventEmitter { options?: IAddRemoveStrokeOptions ) { const effectiveOptions: Required = { - forceReRender: options ? options.forceReRender ?? false : false, - addToChangeLog: options ? options.addToChangeLog ?? true : true, + forceReRender: options ? (options.forceReRender ?? false) : false, + addToChangeLog: options ? (options.addToChangeLog ?? true) : true, }; if (effectiveOptions.forceReRender || this._strokes.has(stroke.id)) { @@ -913,13 +636,13 @@ export class InkingManager extends EventEmitter { this.emit(PointerMovedEvent, eventArgs); } - private notifyStrokesAdded(...strokes: IStroke[]) { + private notifyStrokesAdded(strokes: IStroke[]) { if (strokes.length > 0) { this.emit(StrokesAddedEvent, strokes); } } - private notifyStrokesRemoved(...strokeIds: string[]) { + private notifyStrokesRemoved(strokeIds: string[]) { if (strokeIds.length > 0) { this.emit(StrokesRemovedEvent, strokeIds); } @@ -1156,6 +879,7 @@ export class InkingManager extends EventEmitter { brush: rawStroke.brush, points: rawStroke.points, clientId: InkingManager.localClientId, + version: 1, }); this.addStroke(stroke); @@ -1239,8 +963,12 @@ export class InkingManager extends EventEmitter { public removeStroke(id: string, options?: IAddRemoveStrokeOptions) { if (this._strokes.delete(id)) { const effectiveOptions: Required = { - forceReRender: options ? options.forceReRender ?? false : false, - addToChangeLog: options ? options.addToChangeLog ?? true : true, + forceReRender: options + ? (options.forceReRender ?? false) + : false, + addToChangeLog: options + ? (options.addToChangeLog ?? true) + : true, }; effectiveOptions.forceReRender diff --git a/packages/live-share-canvas/src/core/LiveCanvas-interfaces.ts b/packages/live-share-canvas/src/core/LiveCanvas-interfaces.ts new file mode 100644 index 000000000..bdb313332 --- /dev/null +++ b/packages/live-share-canvas/src/core/LiveCanvas-interfaces.ts @@ -0,0 +1,19 @@ +/** + * Encapsulates information about a user that is okay to be sent through events. + */ +export interface IEventUserInfo { + /** + * Optional. The URI to the user's picture. + */ + pictureUri?: string; +} + +/** + * Encapsulates information about a user. + */ +export interface IUserInfo extends IEventUserInfo { + /** + * Optional. The user's display name. + */ + displayName?: string; +} diff --git a/packages/live-share-canvas/src/core/LiveCanvas.ts b/packages/live-share-canvas/src/core/LiveCanvas.ts index 7bc66ac7f..128daae38 100644 --- a/packages/live-share-canvas/src/core/LiveCanvas.ts +++ b/packages/live-share-canvas/src/core/LiveCanvas.ts @@ -3,376 +3,76 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { DataObjectFactory } from "@fluidframework/aqueduct"; +import { DataObjectFactory } from "@fluidframework/aqueduct/legacy"; import { IFluidHandle } from "@fluidframework/core-interfaces"; -import { IValueChanged, SharedMap } from "@fluidframework/map"; -import { ISequencedDocumentMessage } from "@fluidframework/protocol-definitions"; +import { SharedMap } from "@fluidframework/map/legacy"; +import { InkingManager } from "./InkingManager.js"; +import { IPoint } from "./Geometry.js"; +import { IStroke, StrokeType } from "./Stroke.js"; +import { + UserMeetingRole, + LiveTelemetryLogger, + ILiveEvent, + LiveDataObjectInitializeState, + ExpectedError, + UnexpectedError, +} from "@microsoft/live-share"; +import { + LiveEventScope, + LiveEventTarget, + DynamicObjectRegistry, + LiveDataObject, +} from "@microsoft/live-share/internal"; +import { + BuiltInLiveCursor, + IAddWetStrokePointsEvent, + IBeginWetStrokeEvent, + IPointerMovedEvent, + InkingEventNames, + LivePointerInputProvider, + LiveStroke, + TelemetryEvents, + LiveCanvasStorageSolution, + SharedTreeStorageSolution, + SharedMapStorageSolution, + StorageSolutionEvents, + createUndoRedoStacks, + sanitizeUserPictureUrl, + undoRedo, +} from "./internals/index.js"; +import { ITree, SharedObjectKind, SharedTree, TreeView } from "fluid-framework"; import { - AddPointsEvent, - BeginStrokeEvent, - ClearEvent, IAddPointsEventArgs, IAddRemoveStrokeOptions, IBeginStrokeEventArgs, - InkingManager, IPointerMovedEventArgs, IWetStroke, +} from "./InkingManager-interfaces.js"; +import { + AddPointsEvent, + BeginStrokeEvent, + ClearEvent, PointerMovedEvent, StrokeEndState, StrokesAddedEvent, StrokesRemovedEvent, -} from "./InkingManager"; -import { - IPointerPoint, - getDistanceBetweenPoints, - IPoint, - IRect, - expandRect, -} from "./Geometry"; -import { IStroke, Stroke, StrokeType } from "./Stroke"; -import { - LiveEventScope, - LiveEventTarget, - UserMeetingRole, - DynamicObjectRegistry, - LiveDataObject, - LiveTelemetryLogger, - ILiveEvent, - LiveDataObjectInitializeState, -} from "@microsoft/live-share"; -import { IBrush } from "./Brush"; -import { BasicColors, IColor, lightenColor, toCssRgbaColor } from "./Colors"; -import { TelemetryEvents } from "./internals"; +} from "./InkingManager-constants.js"; +import { IEventUserInfo, IUserInfo } from "./LiveCanvas-interfaces.js"; +import { LiveCursor } from "./LiveCursor.js"; +import type { ISharedObjectKind } from "@fluidframework/shared-object-base/legacy"; import { - IMulticastEvent, - IPointerEvent, - IPointerMoveEvent, - InputProvider, -} from "../input"; - -enum InkingEventNames { - pointerMove = "PointerMove", - beginWetStroke = "BeginWetStroke", - addWetStrokePoints = "AddWetStrokePoint", -} - -/** - * Encapsulates information about a user that is okay to be sent through events. - */ -interface IEventUserInfo { - /** - * Optional. The URI to the user's picture. - */ - pictureUri?: string; -} - -/** - * Encapsulates information about a user. - */ -export interface IUserInfo extends IEventUserInfo { - /** - * Optional. The user's display name. - */ - displayName?: string; -} - -type IPointerMovedEvent = IPointerMovedEventArgs & IEventUserInfo; - -interface ISharedCursor { - isCursorShared?: boolean; -} - -type IBeginWetStrokeEvent = IBeginStrokeEventArgs & - ISharedCursor & - IEventUserInfo; - -type IAddWetStrokePointsEvent = IAddPointsEventArgs & - ISharedCursor & - IEventUserInfo; - -class LiveStroke { - /** - * Configures the delay before wet stroke events are emitted, to greatly reduce the - * number of events emitted and improve performance. - */ - private static readonly wetStrokeEventsStreamDelay = 60; - - private _points: IPointerPoint[] = []; - private _processTimeout?: number; - - private process() { - if (this.type !== StrokeType.persistent) { - return; - } - - let index = 0; - - while (index + 2 < this._points.length) { - const p1 = this._points[index]; - const p2 = this._points[index + 1]; - const p3 = this._points[index + 2]; - - const p1p2 = getDistanceBetweenPoints(p1, p2); - const p2p3 = getDistanceBetweenPoints(p2, p3); - const p1p3 = getDistanceBetweenPoints(p1, p3); - - const threshold = (p1p2 + p2p3) * (100 / p1p3); - - if (threshold < this.simplificationThreshold) { - this._points.splice(index + 1, 1); - } else { - index++; - } - } - } - - endState?: StrokeEndState; - - constructor( - readonly id: string, - readonly type: StrokeType, - readonly brush: IBrush, - readonly simplificationThreshold: number - ) {} - - get points(): IPointerPoint[] { - return this._points; - } - - clear() { - this._points = []; - } - - scheduleProcessing(onProcessedCallback: (stroke: LiveStroke) => void) { - if (this._processTimeout === undefined) { - this._processTimeout = window.setTimeout(() => { - this.process(); - - this._processTimeout = undefined; - - onProcessedCallback(this); - }, LiveStroke.wetStrokeEventsStreamDelay); - } - } -} - -/** - * Represents a live (shared) cursor. Applications that want to customize - * the appearance of cursors on the screen should extend `LiveCursor` and - * override its `renderedElement` property to return a custom HTML element. - */ -export abstract class LiveCursor { - private _renderedElement?: HTMLElement; - private _lastUpdated = Date.now(); - private _userInfo?: IUserInfo; - - protected abstract internalRender(): HTMLElement; - - /** - * Initializes a new instance of `LiveCursor`. - * @param info The cursor info. - */ - constructor(public readonly clientId: string, _userInfo?: IUserInfo) { - this._userInfo = _userInfo; - } - - /** - * Updates the position of the cursor. - * @param position The new position of the cursor. - */ - setPosition(position: IPoint) { - this._lastUpdated = Date.now(); - - if (this.renderedElement) { - this.renderedElement.style.left = position.x + "px"; - this.renderedElement.style.top = position.y + "px"; - } - } - - /** - * @hidden - * Overwrite the user info used for rendering displayName. - * Normally should let LiveCanvas set this value, which comes from the host and is trusted. - * Values set here will be overwritten by values from the host - */ - public set userInfo(value: IUserInfo | undefined) { - this._userInfo = value; - } - - public get userInfo(): IUserInfo | undefined { - return this._userInfo; - } - - /** - * Gets the amount of time the cursor has been idle. - */ - get idleTime() { - return Date.now() - this._lastUpdated; - } - - /** - * Returns an HTML element representing the cursor. Applications - * that extend `LiveCursor` must override `get renderedElement` - * to return a custom built HTML element. - */ - get renderedElement(): HTMLElement { - if (!this._renderedElement) { - this._renderedElement = this.internalRender(); - } - - return this._renderedElement; - } -} - -interface ICursorColor { - readonly backgroundColor: IColor; - readonly textColor: IColor; -} - -class BuiltInLiveCursor extends LiveCursor { - private static cursorColors: ICursorColor[] = [ - { backgroundColor: BasicColors.red, textColor: BasicColors.white }, - { backgroundColor: BasicColors.green, textColor: BasicColors.white }, - { backgroundColor: BasicColors.blue, textColor: BasicColors.white }, - { backgroundColor: BasicColors.purple, textColor: BasicColors.white }, - { backgroundColor: BasicColors.magenta, textColor: BasicColors.white }, - { backgroundColor: BasicColors.violet, textColor: BasicColors.white }, - { backgroundColor: BasicColors.gray, textColor: BasicColors.white }, - { backgroundColor: BasicColors.silver, textColor: BasicColors.black }, - ]; - private static currentColorIndex = 0; - - private _color: ICursorColor; - private _arrowPathData?: string; - private _arrowBounds?: IRect; - - protected internalRender(): HTMLElement { - const arrowPath: IPoint[] = [ - { x: 0, y: 0 }, - { x: 10, y: 30 }, - { x: 17, y: 17 }, - { x: 30, y: 10 }, - ]; - - if (!this._arrowPathData || !this._arrowBounds) { - this._arrowPathData = ""; - - this._arrowBounds = { - left: Number.MAX_VALUE, - top: Number.MAX_VALUE, - right: Number.MIN_VALUE, - bottom: Number.MIN_VALUE, - }; - - for (let i = 0; i < arrowPath.length; i++) { - const p = arrowPath[i]; - - this._arrowBounds = expandRect(this._arrowBounds, p); - - this._arrowPathData += `${i === 0 ? "M" : "L"} ${p.x} ${p.y} `; - } - - this._arrowPathData += "Z"; - } - - const arrowWidth = this._arrowBounds.right - this._arrowBounds.left; - const arrowHeight = this._arrowBounds.bottom - this._arrowBounds.top; - const arrowStrokeWidth = 10; - - const textColor = toCssRgbaColor(this._color.textColor); - const arrowBorderColor = toCssRgbaColor( - lightenColor(this._color.backgroundColor, 80) - ); - const backgroundColor = toCssRgbaColor(this._color.backgroundColor); - - let visualTemplate = ` - - - - `; - - if (this.userInfo) { - if (this.userInfo.displayName && !this.userInfo.pictureUri) { - visualTemplate += ` -
        - ${this.userInfo.displayName} -
        `; - } else if (this.userInfo.pictureUri && !this.userInfo.displayName) { - visualTemplate += ` - `; - } else if (this.userInfo.pictureUri && this.userInfo.displayName) { - visualTemplate += ` -
        - -
        ${ - this.userInfo.displayName - }
        -
        `; - } - } - - const template = document.createElement("template"); - template["innerHTML"] = visualTemplate; - - const element = document.createElement("div"); - element.style.position = "absolute"; - element.style.display = "flex"; - element.style.flexDirection = "row"; - - element.appendChild(template.content.cloneNode(true)); - - return element; - } - - constructor(public clientId: string, _userInfo?: IUserInfo) { - super(clientId, _userInfo); - - this._color = - BuiltInLiveCursor.cursorColors[BuiltInLiveCursor.currentColorIndex]; - - BuiltInLiveCursor.currentColorIndex++; - - if ( - BuiltInLiveCursor.currentColorIndex >= - BuiltInLiveCursor.cursorColors.length - ) { - BuiltInLiveCursor.currentColorIndex = 0; - } - } -} + LiveCanvasStrokesMap, + LiveCanvasTreeNode, + treeViewConfiguration, +} from "./LiveCanvasTreeSchema.js"; /** * Enables live and collaborative inking. */ -export class LiveCanvas extends LiveDataObject { +export class LiveCanvasClass extends LiveDataObject { private _logger?: LiveTelemetryLogger; private static readonly dryInkMapKey = "dryInk"; + private static readonly treeKey = "treeKey"; /** * In order to limit the number of points being sent over the wire, wet strokes are @@ -403,15 +103,24 @@ export class LiveCanvas extends LiveDataObject { * The object's Fluid type factory. */ public static readonly factory = new DataObjectFactory( - LiveCanvas.TypeName, - LiveCanvas, - [], + LiveCanvasClass.TypeName, + LiveCanvasClass, + [ + ( + SharedTree as unknown as ISharedObjectKind & + SharedObjectKind + ).getFactory(), + ], {} ); private _inkingManager?: InkingManager; private _processingIncomingChanges = false; private _dryInkMap!: SharedMap; + private _tree?: ITree; + private _treeView?: TreeView; + private _treeUndoRedo?: undoRedo; + private _storageSolution?: LiveCanvasStorageSolution; private _wetStrokes: Map = new Map< string, IWetStroke @@ -424,9 +133,11 @@ export class LiveCanvas extends LiveDataObject { LiveStroke >(); private _liveCursorsMap = new Map(); - private _liveCursorsHost!: HTMLElement; + private _liveCursorsHost?: HTMLElement; private _isCursorShared: boolean = false; private _liveCursorSweepTimeout?: number; + private _storageListeners: Map = new Map(); + private _inkingManagerListeners: Map = new Map(); private liveStrokeProcessed = (liveStroke: LiveStroke) => { this.onLocalUserAllowed(async () => { @@ -448,100 +159,93 @@ export class LiveCanvas extends LiveDataObject { }; private getLocalUserPictureUrl(): string | undefined { - return this.onGetLocalUserPictureUrl + const pictureUri = this.onGetLocalUserPictureUrl ? this.onGetLocalUserPictureUrl() : undefined; + + return sanitizeUserPictureUrl(pictureUri); } private setupWetInkProcessing(): void { // Setup outgoing events - if (this._inkingManager) { - this._inkingManager.on( - PointerMovedEvent, - (eventArgs: IPointerMovedEventArgs) => { - if (this.isCursorShared) { - this.onLocalUserAllowed(async () => { - try { - // Send a pointer moved event with an undefined - // point to indicated the cursor is not shared anymore - this._pointerMovedEventTarget.sendEvent({ - position: eventArgs.position, - pictureUri: this.getLocalUserPictureUrl(), - }); - } catch (err) { - this._logger?.sendErrorEvent( - TelemetryEvents.LiveCanvas - .PointerMovedEventError, - err - ); - } + if (!this._inkingManager) return; + const pointerEventListener = (eventArgs: IPointerMovedEventArgs) => { + if (this.isCursorShared) { + this.onLocalUserAllowed(async () => { + try { + // Send a pointer moved event with an undefined + // point to indicated the cursor is not shared anymore + this._pointerMovedEventTarget.sendEvent({ + position: eventArgs.position, + pictureUri: this.getLocalUserPictureUrl(), }); + } catch (err) { + this._logger?.sendErrorEvent( + TelemetryEvents.LiveCanvas.PointerMovedEventError, + err + ); } - } + }); + } + }; + this._inkingManager.on(PointerMovedEvent, pointerEventListener); + this._inkingManagerListeners.set( + PointerMovedEvent, + pointerEventListener + ); + const beginStrokeListener = (eventArgs: IBeginStrokeEventArgs) => { + const liveStroke = new LiveStroke( + eventArgs.strokeId, + eventArgs.type, + eventArgs.brush, + LiveCanvas.wetStrokePointSimplificationThreshold ); - this._inkingManager.on( - BeginStrokeEvent, - (eventArgs: IBeginStrokeEventArgs) => { - const liveStroke = new LiveStroke( - eventArgs.strokeId, - eventArgs.type, - eventArgs.brush, - LiveCanvas.wetStrokePointSimplificationThreshold - ); - liveStroke.points.push(eventArgs.startPoint); - - this._pendingLiveStrokes.set(liveStroke.id, liveStroke); - - this.onLocalUserAllowed(async () => { - // Send the begin wet stroke event - try { - this._beginWetStrokeEventTarget.sendEvent({ - isCursorShared: this.isCursorShared - ? true - : undefined, - pictureUri: this.getLocalUserPictureUrl(), - ...eventArgs, - }); - } catch (err) { - this._logger?.sendErrorEvent( - TelemetryEvents.LiveCanvas.BeginWetStrokeError, - err - ); - } + liveStroke.points.push(eventArgs.startPoint); + + this._pendingLiveStrokes.set(liveStroke.id, liveStroke); + + this.onLocalUserAllowed(async () => { + // Send the begin wet stroke event + try { + this._beginWetStrokeEventTarget.sendEvent({ + isCursorShared: this.isCursorShared ? true : undefined, + pictureUri: this.getLocalUserPictureUrl(), + ...eventArgs, }); - } - ); - this._inkingManager.on( - AddPointsEvent, - (eventArgs: IAddPointsEventArgs) => { - const liveStroke = this._pendingLiveStrokes.get( - eventArgs.strokeId + } catch (err) { + this._logger?.sendErrorEvent( + TelemetryEvents.LiveCanvas.BeginWetStrokeError, + err ); + } + }); + }; + this._inkingManager.on(BeginStrokeEvent, beginStrokeListener); + this._inkingManagerListeners.set(BeginStrokeEvent, beginStrokeListener); + const addPointListener = (eventArgs: IAddPointsEventArgs) => { + const liveStroke = this._pendingLiveStrokes.get(eventArgs.strokeId); + + if (liveStroke !== undefined) { + if (!eventArgs.endState && eventArgs.points.length > 0) { + liveStroke.points.push(...eventArgs.points); + } - if (liveStroke !== undefined) { - if ( - !eventArgs.endState && - eventArgs.points.length > 0 - ) { - liveStroke.points.push(...eventArgs.points); - } - - liveStroke.endState = eventArgs.endState; + liveStroke.endState = eventArgs.endState; - if (eventArgs.endState) { - this._pendingLiveStrokes.delete(eventArgs.strokeId); - } + if (eventArgs.endState) { + this._pendingLiveStrokes.delete(eventArgs.strokeId); + } - if (eventArgs.points.length > 0) { - liveStroke.scheduleProcessing( - this.liveStrokeProcessed - ); - } - } + if (eventArgs.points.length > 0) { + liveStroke.scheduleProcessing(this.liveStrokeProcessed); } - ); - } + } + }; + this._inkingManager.on(AddPointsEvent, addPointListener); + this._inkingManagerListeners.set(AddPointsEvent, addPointListener); + + if (this._pointerMovedEventTarget) return; // Setup incoming events const scope = new LiveEventScope( @@ -580,6 +284,7 @@ export class LiveCanvas extends LiveDataObject { clientId: evt.clientId, timeStamp: evt.timestamp, brush: evt.data.brush, + version: 1, } ); @@ -652,105 +357,143 @@ export class LiveCanvas extends LiveDataObject { ); } - private setupStorageProcessing(): void { + private setupStorageProcessing(node?: LiveCanvasTreeNode): void { if (this._inkingManager) { const inkingManager = this._inkingManager; + const treeNode = node ?? this._treeView?.root; + if (treeNode) { + this._storageSolution = new SharedTreeStorageSolution( + treeNode, + inkingManager + ); + } else { + this._storageSolution = new SharedMapStorageSolution( + this._dryInkMap, + inkingManager + ); + } // Setup incoming dry ink changes - this._dryInkMap.forEach((value: string) => { - const stroke = new Stroke(); - stroke.deserialize(value); - + this._storageSolution.forEach((stroke: IStroke) => { inkingManager.addStroke(stroke); }); - this._dryInkMap.on( - "valueChanged", - (changed: IValueChanged, local: boolean): void => { - this._processingIncomingChanges = true; - - try { - if (!local) { - const serializedStroke: string | undefined = - this._dryInkMap.get(changed.key); - const addRemoveOptions: IAddRemoveStrokeOptions = { - forceReRender: true, - addToChangeLog: false, - }; - - if (serializedStroke !== undefined) { - const stroke = - inkingManager.getStroke(changed.key) ?? - new Stroke(); - stroke.deserialize(serializedStroke); - - // If we received a stroke that happens to be an ongoing wet stroke, - // cancel the wet stroke so it's removed from the screen and replace - // it with the full fidelity version we just received. - const wetStroke = this._wetStrokes.get( - stroke.id - ); + const onStrokeRemovedListener = ( + strokeId: string, + local: boolean + ) => { + if (local) return; + this._processingIncomingChanges = true; + try { + const addRemoveOptions: IAddRemoveStrokeOptions = { + forceReRender: true, + addToChangeLog: false, + }; + inkingManager.removeStroke(strokeId, addRemoveOptions); + } finally { + this._processingIncomingChanges = false; + } + }; + this._storageSolution.on( + StorageSolutionEvents.strokeRemoved, + onStrokeRemovedListener + ); + this._storageListeners.set( + StorageSolutionEvents.strokeRemoved, + onStrokeRemovedListener + ); - if (wetStroke) { - wetStroke.cancel(); + const onStrokeChangedListener = ( + stroke: IStroke, + local: boolean + ): void => { + if (local) return; + this._processingIncomingChanges = true; + + try { + const addRemoveOptions: IAddRemoveStrokeOptions = { + forceReRender: true, + addToChangeLog: false, + }; + // If we received a stroke that happens to be an ongoing wet stroke, + // cancel the wet stroke so it's removed from the screen and replace + // it with the full fidelity version we just received. + const wetStroke = this._wetStrokes.get(stroke.id); - this._wetStrokes.delete(wetStroke.id); - } + if (wetStroke) { + wetStroke.cancel(); - inkingManager.addStroke( - stroke, - addRemoveOptions - ); - } else { - inkingManager.removeStroke( - changed.key, - addRemoveOptions - ); - } - } - } finally { - this._processingIncomingChanges = false; + this._wetStrokes.delete(wetStroke.id); } + + inkingManager.addStroke(stroke, addRemoveOptions); + } finally { + this._processingIncomingChanges = false; } + }; + this._storageSolution.on( + StorageSolutionEvents.strokeChanged, + onStrokeChangedListener + ); + this._storageListeners.set( + StorageSolutionEvents.strokeChanged, + onStrokeChangedListener ); - this._dryInkMap.on( - "op", - (op: ISequencedDocumentMessage, local: boolean): void => { - this._processingIncomingChanges = true; + const onStrokesClearedListener = (local: boolean): void => { + if (local) return; + this._processingIncomingChanges = true; - try { - if (!local) { - if (op.contents.type === "clear") { - inkingManager.clear(); - } - } - } finally { - this._processingIncomingChanges = false; - } + try { + inkingManager.clear(); + } finally { + this._processingIncomingChanges = false; } + }; + this._storageSolution.on( + StorageSolutionEvents.strokesCleared, + onStrokesClearedListener + ); + this._storageListeners.set( + StorageSolutionEvents.strokesCleared, + onStrokesClearedListener ); // Setup outgoing dry ink changes. - inkingManager.on(StrokesAddedEvent, (strokes: IStroke[]): void => { + const onStrokesAddedListener = (strokes: IStroke[]): void => { if (!this._processingIncomingChanges) { for (let stroke of strokes) { - this._dryInkMap.set(stroke.id, stroke.serialize()); + this._storageSolution?.set(stroke); } } - }); - inkingManager.on(StrokesRemovedEvent, (ids: string[]): void => { + }; + inkingManager.on(StrokesAddedEvent, onStrokesAddedListener); + this._inkingManagerListeners.set( + StrokesAddedEvent, + onStrokesAddedListener + ); + const onStrokesRemovedEventListener = (ids: string[]): void => { if (!this._processingIncomingChanges) { for (let id of ids) { - this._dryInkMap.delete(id); + this._storageSolution?.delete(id); } } - }); - inkingManager.on(ClearEvent, (): void => { + }; + inkingManager.on( + StrokesRemovedEvent, + onStrokesRemovedEventListener + ); + this._inkingManagerListeners.set( + StrokesRemovedEvent, + onStrokesRemovedEventListener + ); + const onClearEventListener = (): void => { if (!this._processingIncomingChanges) { - this._dryInkMap.clear(); + this._storageSolution?.clear(); } - }); + }; + inkingManager.on(ClearEvent, onClearEventListener); + this._inkingManagerListeners.set(ClearEvent, onClearEventListener); } } @@ -795,8 +538,8 @@ export class LiveCanvas extends LiveDataObject { liveCursor.userInfo = userInfo; } - if (!this._liveCursorsHost.contains(liveCursor.renderedElement)) { - this._liveCursorsHost.appendChild(liveCursor.renderedElement); + if (!this._liveCursorsHost?.contains(liveCursor.renderedElement)) { + this._liveCursorsHost?.appendChild(liveCursor.renderedElement); } this.scheduleLiveCursorSweep(); @@ -808,7 +551,7 @@ export class LiveCanvas extends LiveDataObject { const liveCursor = this._liveCursorsMap.get(clientId); if (liveCursor) { - if (this._liveCursorsHost.contains(liveCursor.renderedElement)) { + if (this._liveCursorsHost?.contains(liveCursor.renderedElement)) { this._liveCursorsHost.removeChild(liveCursor.renderedElement); } } @@ -827,7 +570,9 @@ export class LiveCanvas extends LiveDataObject { if (this._inkingManager) { const userInfo: IUserInfo = { displayName: clientInfo?.displayName, - pictureUri: eventUserInfo?.pictureUri, + pictureUri: sanitizeUserPictureUrl( + eventUserInfo?.pictureUri + ), }; const liveCursor = this.getCursor(clientId, userInfo); @@ -842,27 +587,59 @@ export class LiveCanvas extends LiveDataObject { } } + private clearListeners() { + this._storageListeners.forEach((listener, key) => { + this._storageSolution?.off(key, listener as any); + }); + this._inkingManagerListeners.forEach((listener, key) => { + this._inkingManager?.off(key, listener as any); + }); + } + protected async initializingFirstTime(): Promise { this._dryInkMap = SharedMap.create( this.runtime, LiveCanvas.dryInkMapKey ); + this._tree = ( + SharedTree as unknown as ISharedObjectKind & + SharedObjectKind + ).create(this.runtime, LiveCanvas.treeKey); + const view = this._tree.viewWith(treeViewConfiguration); + view.initialize( + new LiveCanvasTreeNode({ + dryInkMap: new LiveCanvasStrokesMap([]), + }) + ); + view.dispose(); this.root.set(LiveCanvas.dryInkMapKey, this._dryInkMap.handle); + this.root.set(LiveCanvas.treeKey, this._tree.handle); } protected async hasInitialized(): Promise { - const handle = this.root.get>( + const mapHandle = this.root.get>( LiveCanvas.dryInkMapKey ); - if (handle) { - this._dryInkMap = await handle.get(); + if (mapHandle) { + this._dryInkMap = await mapHandle.get(); } else { throw new Error( `Unable to get SharedMap with key "${LiveCanvas.dryInkMapKey}"` ); } + + const treeHandle = this.root.get>( + LiveCanvas.treeKey + ); + if (treeHandle) { + // Legacy containers will not have `_tree` and will have to fall back to `_dryInkMap` + this._tree = await treeHandle.get(); + this._treeView = this._tree.viewWith(treeViewConfiguration); + this._treeUndoRedo = createUndoRedoStacks(this._treeView.events); + // TODO: listen for changes to root, pretty minor since we don't ever set it outside of the first time + } } /** @@ -883,13 +660,21 @@ export class LiveCanvas extends LiveDataObject { * Initializes the live inking session. * * @param inkingManager The InkingManager instance providing the drawing and events that will be synchronized across clients. + * @param allowedRoles Optional. Roles who are allowed to draw strokes + * @param node Optional. A Fluid `LiveCanvasTree` `TreeNode` instance to swap out the underlying storage solution for strokes. + * To learn more, look at Fluid's [SharedTree](https://fluidframework.com/docs/data-structures/tree/) documentation. * * @returns a void promise that resolves once complete. */ async initialize( inkingManager: InkingManager, - allowedRoles?: UserMeetingRole[] + allowedRoles?: UserMeetingRole[], + node?: LiveCanvasTreeNode ) { + // Cleanup if already + this.clearListeners(); + this._storageSolution?.dispose(); + // Update initialize state as pending this.initializeState = LiveDataObjectInitializeState.pending; @@ -903,7 +688,7 @@ export class LiveCanvas extends LiveDataObject { ); this._logger = new LiveTelemetryLogger(this.runtime, this.liveRuntime); - this.setupStorageProcessing(); + this.setupStorageProcessing(node); this.setupWetInkProcessing(); this._liveCursorsHost = document.createElement("div"); @@ -912,13 +697,89 @@ export class LiveCanvas extends LiveDataObject { this._liveCursorsHost.style.width = "100%"; this._liveCursorsHost.style.height = "100%"; this._liveCursorsHost.style.overflow = "hidden"; - inkingManager.hostElement.appendChild(this._liveCursorsHost); // Update initialize state as succeeded this.initializeState = LiveDataObjectInitializeState.succeeded; } + /** + * Changes the underlying {@link LiveCanvasTreeNode} node used for storing inking strokes. + * To learn more, look at Fluid's [SharedTree](https://fluidframework.com/docs/data-structures/tree/) documentation. + * @remarks + * There is a default `LiveCanvasTree` node that is created for each `LiveCanvas`. + * The purpose of this is to allow you to use a single `LiveCanvas` instance with an interchangable data source. + * This will not cause the default `LiveCanvasTree` node to be deleted. + */ + setTreeNode(node: LiveCanvasTreeNode) { + // Legacy containers that only have _dryInkMap are not supported + ExpectedError.assert( + !this._treeView, + "LiveCanvas:setTreeNode", + "Cannot call `setTreeNode` on a 1.0 `LiveCanvas` instance using `SharedMap`.", + 'To fix this issue, create a new Fluid container or `LiveCanvas` instance. You can also proactively check if this API is available using `LiveCanvas.ddsVersion === "2.0"`.' + ); + // Cleanup existing + this._storageSolution?.dispose(); + this.clearListeners(); + this._inkingManager?.clear(); + // Resetup storage & inking + this.setupStorageProcessing(node); + this.setupWetInkProcessing(); + } + + /** + * Undo the most recent stroke in this `LiveCanvas` instance's {@link LiveCanvasTreeNode} node. + * + * @remarks + * Only works in {@link ddsVersion} 2.0 and when using the default {@link LiveCanvasTreeNode} node as the data source. + * If you use your own `node` to {@link initialize} or {@link setTreeNode}, undo/redo must be handled via your root `TreeView`. + */ + undo() { + ExpectedError.assert( + this.ddsVersion === "2.0", + "LiveCanvas:undo", + "Cannot call `undo` on a 1.0 `LiveCanvas` instance using `SharedMap`.", + 'To fix this issue, create a new Fluid container or `LiveCanvas` instance. You can also proactively check if this API is available using `LiveCanvas.ddsVersion === "2.0"`.' + ); + UnexpectedError.assert( + !!this._treeUndoRedo, + "LiveCanvas:undo", + "`this._treeUndoRedo` is unexpectedly undefined despite `this.ddsVersion` being 2.0, which is a valid version." + ); + this._treeUndoRedo.undo(); + } + + /** + * Redo the most recent stroke in this `LiveCanvas` instance's {@link LiveCanvasTreeNode} node. + * + * @remarks + * Only works in {@link ddsVersion} 2.0 and when using the default {@link LiveCanvasTreeNode} node as the data source. + * If you use your own `node` to {@link initialize} or {@link setTreeNode}, undo/redo must be handled via your root `TreeView`. + */ + redo() { + ExpectedError.assert( + this.ddsVersion === "2.0", + "LiveCanvas:redo", + "Cannot call `redo` on a 1.0 `LiveCanvas` instance using `SharedMap`.", + 'To fix this issue, create a new Fluid container or `LiveCanvas` instance. You can also proactively check if this API is available using `LiveCanvas.ddsVersion === "2.0"`.' + ); + UnexpectedError.assert( + !!this._treeUndoRedo, + "LiveCanvas:redo", + "`this._treeUndoRedo` is unexpectedly undefined despite `this.ddsVersion` being 2.0, which is a valid version." + ); + this._treeUndoRedo.redo(); + } + + override dispose() { + this.clearListeners(); + this._treeView?.dispose(); + this._storageSolution?.dispose(); + this._treeUndoRedo?.dispose(); + super.dispose(); + } + /** * Gets the current cursor sharing status of this client. */ @@ -958,67 +819,32 @@ export class LiveCanvas extends LiveDataObject { } /** - * Sets the list of roles that are allowed to emit wet stroke events. + * Returns 2.0 if the `LiveCanvas` instance was created in `@microsoft/live-share-canvas` >=2.0.0. + * Otherwise, returns 1.0. + * @remarks + * Intended to know when it is safe to set the `node` prop in {@link initialize} or {@link setTreeNode}. + * Also helpful for knowing whether {@link undo} or {@link redo} will work. */ - set allowedRoles(value: UserMeetingRole[]) { - this._allowedRoles = value; - - this.setupWetInkProcessing(); + get ddsVersion(): "1.0" | "2.0" { + if (!this._treeView) { + return "1.0"; + } + return "2.0"; } } /** - * @hidden - * Decorator for InputProvider that ensures local user has correct - * roles before activating delegate input provider. + * Enables live and collaborative inking. */ -class LivePointerInputProvider extends InputProvider { - constructor( - private delegate: InputProvider, - private verifyLocalUserRoles: () => Promise - ) { - super(); - } - activate() { - this.verifyLocalUserRoles().then((allowed) => { - if (allowed) { - this.delegate.activate(); - } else { - this.delegate.deactivate(); - } - }); - } - - deactivate() { - this.delegate.deactivate(); - } - - get isActive(): boolean { - return this.delegate.isActive; - } - - get pointerDown(): IMulticastEvent { - return this.delegate.pointerDown; - } +export type LiveCanvas = LiveCanvasClass; - get pointerMove(): IMulticastEvent { - return this.delegate.pointerMove; - } - - get pointerUp(): IMulticastEvent { - return this.delegate.pointerUp; - } - - get pointerEnter(): IMulticastEvent { - return this.delegate.pointerEnter; - } - - get pointerLeave(): IMulticastEvent { - return this.delegate.pointerLeave; - } -} +// eslint-disable-next-line no-redeclare +export const LiveCanvas = (() => { + const kind = LiveCanvasClass; + return kind as typeof kind & SharedObjectKind; +})(); /** - * Register `LiveCanvas` as an available `LoadableObjectClass` for use in packages that support dynamic object loading, such as `@microsoft/live-share-turbo`. + * Register `LiveCanvas` as an available `SharedObjectKind` for use in dynamic object loading. */ DynamicObjectRegistry.registerObjectClass(LiveCanvas, LiveCanvas.TypeName); diff --git a/packages/live-share-canvas/src/core/LiveCanvasTreeSchema.ts b/packages/live-share-canvas/src/core/LiveCanvasTreeSchema.ts new file mode 100644 index 000000000..cdf904832 --- /dev/null +++ b/packages/live-share-canvas/src/core/LiveCanvasTreeSchema.ts @@ -0,0 +1,133 @@ +import { SchemaFactory, Tree, TreeViewConfiguration } from "fluid-framework"; +import { LiveCanvas } from "./LiveCanvas.js"; +import { IBrush } from "./Brush.js"; +import { IStroke, Stroke } from "./Stroke.js"; +import { IColor } from "./Colors.js"; + +/** + * The `SchemaFactory` used in the `SharedTree` instance of {@link LiveCanvas}. + */ +export const sf = new SchemaFactory( + "LiveCanvas-99059925-e384-44af-82ae-31c5a824cb46" +); + +/** + * `SharedTree` for {@link IColor} + */ +export class LiveCanvasColor extends sf.object("Color", { + r: sf.number, + g: sf.number, + b: sf.number, +}) {} + +/** + * `SharedTree` schema for {@link IBrush}. + */ +export class LiveCanvasBrush extends sf.object("Brush", { + type: sf.string, + color: LiveCanvasColor, + tip: sf.string, + tipSize: sf.number, + endArrow: sf.optional(sf.string), +}) {} + +/** + * `SharedTree` schema for {@link Stroke}. + */ +export class LiveCanvasStroke extends sf.object("LiveCanvasStroke", { + /** + * Unique id of stroke + */ + id: sf.string, + /** + * Version number of stroke + */ + version: sf.number, + /** + * Client id that made the stroke + */ + clientId: sf.optional(sf.string), + /** + * Timestamp the stroke was created + */ + timestamp: sf.number, + /** + * Type of brush. + * See {@link IBrush} + */ + brush: LiveCanvasBrush, + /** + * Serialized points + */ + points: sf.string, +}) { + private get serializeString(): string { + const strokeData = { + v: this.version, + id: this.id, + cId: this.clientId, + t: this.timestamp, + br: this.brush, + d: this.points, + }; + + return JSON.stringify(strokeData); + } + deserialize(existingStroke?: IStroke): IStroke { + const stroke = existingStroke ?? new Stroke(); + stroke.deserialize(this.serializeString); + return stroke; + } + + static fromStroke(stroke: IStroke): LiveCanvasStroke { + return new LiveCanvasStroke({ + id: stroke.id, + version: stroke.version, + clientId: stroke.clientId, + timestamp: stroke.timeStamp, + brush: new LiveCanvasBrush({ + type: stroke.brush.type, + color: new LiveCanvasColor({ + ...stroke.brush.color, + }), + tip: stroke.brush.tip, + tipSize: stroke.brush.tipSize, + endArrow: stroke.brush.endArrow, + }), + points: stroke.serializePoints(), + }); + } +} + +/** + * `SharedTree` schema for map of {@link LiveCanvasStroke} nodes. + */ +export class LiveCanvasStrokesMap extends sf.map( + "LiveCanvasStrokesMap", + LiveCanvasStroke +) { + /** + * Clear all strokes in the map + */ + clear() { + Tree.runTransaction(this, (node) => { + node.forEach((child) => { + node.delete(child.id); + }); + }); + } +} + +/** + * `SharedTree` schema used by {@link LiveCanvas} + */ +export class LiveCanvasTreeNode extends sf.object("LiveCanvasTree", { + dryInkMap: LiveCanvasStrokesMap, +}) {} + +/** + * @hidden + */ +export const treeViewConfiguration = new TreeViewConfiguration({ + schema: LiveCanvasTreeNode, +}); diff --git a/packages/live-share-canvas/src/core/LiveCursor.ts b/packages/live-share-canvas/src/core/LiveCursor.ts new file mode 100644 index 000000000..a7f14f99f --- /dev/null +++ b/packages/live-share-canvas/src/core/LiveCursor.ts @@ -0,0 +1,73 @@ +import { IPoint } from "./Geometry.js"; +import { IUserInfo } from "./LiveCanvas-interfaces.js"; + +/** + * Represents a live (shared) cursor. Applications that want to customize + * the appearance of cursors on the screen should extend `LiveCursor` and + * override its `renderedElement` property to return a custom HTML element. + */ +export abstract class LiveCursor { + private _renderedElement?: HTMLElement; + private _lastUpdated = Date.now(); + private _userInfo?: IUserInfo; + + protected abstract internalRender(): HTMLElement; + + /** + * Initializes a new instance of `LiveCursor`. + * @param info The cursor info. + */ + constructor( + public readonly clientId: string, + _userInfo?: IUserInfo + ) { + this._userInfo = _userInfo; + } + + /** + * Updates the position of the cursor. + * @param position The new position of the cursor. + */ + setPosition(position: IPoint) { + this._lastUpdated = Date.now(); + + if (this.renderedElement) { + this.renderedElement.style.left = position.x + "px"; + this.renderedElement.style.top = position.y + "px"; + } + } + + /** + * @hidden + * Overwrite the user info used for rendering displayName. + * Normally should let LiveCanvas set this value, which comes from the host and is trusted. + * Values set here will be overwritten by values from the host + */ + public set userInfo(value: IUserInfo | undefined) { + this._userInfo = value; + } + + public get userInfo(): IUserInfo | undefined { + return this._userInfo; + } + + /** + * Gets the amount of time the cursor has been idle. + */ + get idleTime() { + return Date.now() - this._lastUpdated; + } + + /** + * Returns an HTML element representing the cursor. Applications + * that extend `LiveCursor` must override `get renderedElement` + * to return a custom built HTML element. + */ + get renderedElement(): HTMLElement { + if (!this._renderedElement) { + this._renderedElement = this.internalRender(); + } + + return this._renderedElement; + } +} diff --git a/packages/live-share-canvas/src/core/Stroke.ts b/packages/live-share-canvas/src/core/Stroke.ts index f662a730c..a989cf223 100644 --- a/packages/live-share-canvas/src/core/Stroke.ts +++ b/packages/live-share-canvas/src/core/Stroke.ts @@ -3,7 +3,7 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { IBrush, DefaultPenBrush } from "./Brush"; +import { IBrush, DefaultPenBrush } from "./Brush.js"; import { getSquaredDistanceBetweenPoints, IPoint, @@ -11,7 +11,7 @@ import { IRect, ISegment, expandRect, -} from "./Geometry"; +} from "./Geometry.js"; import { doRectanglesOverlap, getSegmentIntersectionsWithRectangle, @@ -20,7 +20,7 @@ import { isRectangleInsideRectangle, segmentMayIntersectWithRectangle, generateUniqueId, -} from "./internals"; +} from "./internals/index.js"; /** * Field names on this interface are intentionally short to minimize @@ -152,6 +152,14 @@ export interface IStroke { * @param serializedStroke The serialized stroke. */ deserialize(serializedStroke: string): void; + /** + * Serialize points + */ + serializePoints(): string; + /** + * Version + */ + readonly version: number; /** * The id of the stroke. */ @@ -179,6 +187,7 @@ export interface IStroke { */ export interface IStrokeCreationOptions { id?: string; + version?: number; clientId?: string; timeStamp?: number; brush?: IBrush; @@ -191,11 +200,14 @@ export interface IStrokeCreationOptions { export class Stroke implements IStroke, Iterable { private static readonly coordinateSerializationPrecision = 1; private static readonly pressureSerializationPrecision = 2; + private _version: number = 1; // Version is fixed at 1 for now. If/when we evolve the structure // of a stroke, we'll update the version number and the // serialization/deserialization logic - private _version: number = 1; + get version(): number { + return this._version; + } private _brush: IBrush = { ...DefaultPenBrush }; private _points: IPointerPoint[]; @@ -218,7 +230,7 @@ export class Stroke implements IStroke, Iterable { * * @returns The serialized points. */ - private serializePoints(): string { + public serializePoints(): string { let result = ""; const coordinateMultiplier = Math.pow( @@ -321,11 +333,12 @@ export class Stroke implements IStroke, Iterable { */ constructor(options?: IStrokeCreationOptions) { const effectiveOptions: IStrokeCreationOptions = { - id: options ? options.id : undefined, - clientId: options ? options.clientId : undefined, - timeStamp: options ? options.timeStamp : undefined, - brush: options ? options.brush : undefined, - points: options ? options.points : undefined, + id: options?.id, + clientId: options?.clientId, + timeStamp: options?.timeStamp, + brush: options?.brush, + points: options?.points, + version: options?.version ?? 1, }; this._id = effectiveOptions.id ?? generateUniqueId(); @@ -499,6 +512,7 @@ export class Stroke implements IStroke, Iterable { clientId: this.clientId, timeStamp: this.timeStamp, brush: this.brush, + version: this.version, }); }; @@ -598,7 +612,7 @@ export class Stroke implements IStroke, Iterable { */ serialize(): string { const strokeData: ISerializedStrokeData = { - v: this._version, + v: this.version, id: this.id, cId: this.clientId, t: this.timeStamp, diff --git a/packages/live-share-canvas/src/core/index.ts b/packages/live-share-canvas/src/core/index.ts index d6712ce60..c5c821a11 100644 --- a/packages/live-share-canvas/src/core/index.ts +++ b/packages/live-share-canvas/src/core/index.ts @@ -3,9 +3,14 @@ * Licensed under the Microsoft Live Share SDK License. */ -export * from "./Brush"; -export * from "./Colors"; -export * from "./Geometry"; -export * from "./InkingManager"; -export * from "./LiveCanvas"; -export * from "./Stroke"; +export * from "./Brush.js"; +export * from "./Colors.js"; +export * from "./Geometry.js"; +export * from "./InkingManager.js"; +export * from "./InkingManager-constants.js"; +export * from "./InkingManager-interfaces.js"; +export * from "./LiveCanvas.js"; +export * from "./LiveCanvas-interfaces.js"; +export * from "./LiveCanvasTreeSchema.js"; +export * from "./LiveCursor.js"; +export * from "./Stroke.js"; diff --git a/packages/live-share-canvas/src/core/internals/BuiltInLiveCursor.ts b/packages/live-share-canvas/src/core/internals/BuiltInLiveCursor.ts new file mode 100644 index 000000000..e7ce22bc8 --- /dev/null +++ b/packages/live-share-canvas/src/core/internals/BuiltInLiveCursor.ts @@ -0,0 +1,242 @@ +import { BasicColors, lightenColor, toCssRgbaColor } from "../Colors.js"; +import { IPoint, IRect, expandRect } from "../Geometry.js"; +import { IUserInfo } from "../LiveCanvas-interfaces.js"; +import { LiveCursor } from "../LiveCursor.js"; +import { ICursorColor } from "./LiveCanvas-interfaces-internal.js"; + +/** + * @internal + */ +export class BuiltInLiveCursor extends LiveCursor { + private static currentColorIndex = 0; + private static readonly svgNamespace = "http://www.w3.org/2000/svg"; + + private _color: ICursorColor; + private _arrowPathData?: string; + private _arrowBounds?: IRect; + + private createArrowElement( + arrowStrokeWidth: number, + arrowWidth: number, + arrowHeight: number, + arrowBorderColor: string, + backgroundColor: string + ): SVGSVGElement { + const svg = document.createElementNS( + BuiltInLiveCursor.svgNamespace, + "svg" + ); + svg.setAttribute( + "viewBox", + `-${arrowStrokeWidth} -${arrowStrokeWidth} ${ + 2 * arrowStrokeWidth + arrowWidth + } ${2 * arrowStrokeWidth + arrowHeight}` + ); + svg.setAttribute("width", `${arrowWidth}`); + svg.setAttribute("height", `${arrowHeight}`); + svg.style.filter = "drop-shadow(0px 0px 1px rgba(0, 0, 0, .7))"; + + const borderPath = document.createElementNS( + BuiltInLiveCursor.svgNamespace, + "path" + ); + borderPath.setAttribute("d", this._arrowPathData ?? ""); + borderPath.setAttribute("stroke", arrowBorderColor); + borderPath.setAttribute("stroke-width", String(arrowStrokeWidth)); + borderPath.setAttribute("stroke-linejoin", "round"); + borderPath.setAttribute("stroke-opacity", "0.90"); + + const fillPath = document.createElementNS( + BuiltInLiveCursor.svgNamespace, + "path" + ); + fillPath.setAttribute("d", this._arrowPathData ?? ""); + fillPath.setAttribute("fill", backgroundColor); + fillPath.setAttribute("stroke", backgroundColor); + fillPath.setAttribute("stroke-width", "2"); + fillPath.setAttribute("stroke-linejoin", "round"); + + svg.appendChild(borderPath); + svg.appendChild(fillPath); + + return svg; + } + + private createPictureElement( + arrowHeight: number, + arrowWidth: number + ): HTMLImageElement { + const image = document.createElement("img"); + + image.setAttribute("src", this.userInfo?.pictureUri ?? ""); + image.setAttribute("alt", ""); + image.setAttribute("aria-hidden", "true"); + image.style.width = `${arrowHeight * 1.1}px`; + image.style.height = `${arrowHeight * 1.1}px`; + image.style.borderRadius = "50%"; + image.style.margin = `${arrowHeight * 0.75}px 0 0 -${ + arrowWidth * 0.25 + }px`; + + return image; + } + + protected internalRender(): HTMLElement { + const arrowPath: IPoint[] = [ + { x: 0, y: 0 }, + { x: 10, y: 30 }, + { x: 17, y: 17 }, + { x: 30, y: 10 }, + ]; + + if (!this._arrowPathData || !this._arrowBounds) { + this._arrowPathData = ""; + + this._arrowBounds = { + left: Number.MAX_VALUE, + top: Number.MAX_VALUE, + right: Number.MIN_VALUE, + bottom: Number.MIN_VALUE, + }; + + for (let i = 0; i < arrowPath.length; i++) { + const p = arrowPath[i]; + + this._arrowBounds = expandRect(this._arrowBounds, p); + + this._arrowPathData += `${i === 0 ? "M" : "L"} ${p.x} ${p.y} `; + } + + this._arrowPathData += "Z"; + } + + const arrowWidth = this._arrowBounds.right - this._arrowBounds.left; + const arrowHeight = this._arrowBounds.bottom - this._arrowBounds.top; + const arrowStrokeWidth = 10; + + const textColor = toCssRgbaColor(this._color.textColor); + const arrowBorderColor = toCssRgbaColor( + lightenColor(this._color.backgroundColor, 80) + ); + const backgroundColor = toCssRgbaColor(this._color.backgroundColor); + + const element = document.createElement("div"); + element.style.position = "absolute"; + element.style.display = "flex"; + element.style.flexDirection = "row"; + + element.appendChild( + this.createArrowElement( + arrowStrokeWidth, + arrowWidth, + arrowHeight, + arrowBorderColor, + backgroundColor + ) + ); + + if (this.userInfo) { + if (this.userInfo.displayName && !this.userInfo.pictureUri) { + const nameElement = document.createElement("div"); + nameElement.style.display = "flex"; + nameElement.style.alignItems = "center"; + nameElement.style.boxShadow = "0 0 2px black"; + nameElement.style.backgroundColor = backgroundColor; + nameElement.style.height = `${arrowHeight}px`; + nameElement.style.color = textColor; + nameElement.style.borderRadius = `${arrowHeight / 2}px / 50%`; + nameElement.style.borderTopLeftRadius = "4px"; + nameElement.style.padding = "2px 8px"; + nameElement.style.margin = `${arrowHeight * 0.75}px 0 0 -${ + arrowWidth * 0.25 + }px`; + nameElement.style.whiteSpace = "nowrap"; + nameElement.style.fontSize = "12px"; + nameElement.style.fontFamily = "sans-serif"; + nameElement.textContent = this.userInfo.displayName; + + element.appendChild(nameElement); + } else if (this.userInfo.pictureUri && !this.userInfo.displayName) { + const imageElement = this.createPictureElement( + arrowHeight, + arrowWidth + ); + imageElement.style.boxShadow = "0 0 2px black"; + + element.appendChild(imageElement); + } else if (this.userInfo.pictureUri && this.userInfo.displayName) { + const container = document.createElement("div"); + container.style.display = "flex"; + container.style.flexDirection = "row"; + container.style.alignItems = "center"; + container.style.backgroundColor = backgroundColor; + container.style.color = textColor; + container.style.borderRadius = `${arrowHeight / 2}px / 50%`; + container.style.margin = `${arrowHeight * 0.75}px 0 0 -${ + arrowWidth * 0.25 + }px`; + container.style.padding = "2px"; + container.style.whiteSpace = "nowrap"; + container.style.fontSize = "12px"; + container.style.fontFamily = "sans-serif"; + container.style.boxShadow = "0 0 2px black"; + + const imageElement = this.createPictureElement( + arrowHeight, + arrowWidth + ); + imageElement.style.margin = "0"; + + const nameElement = document.createElement("div"); + nameElement.style.padding = "0 8px"; + nameElement.textContent = this.userInfo.displayName; + + container.appendChild(imageElement); + container.appendChild(nameElement); + element.appendChild(container); + } + } + + return element; + } + + constructor( + public clientId: string, + _userInfo?: IUserInfo + ) { + const cursorColors: ICursorColor[] = [ + { backgroundColor: BasicColors.red, textColor: BasicColors.white }, + { + backgroundColor: BasicColors.green, + textColor: BasicColors.white, + }, + { backgroundColor: BasicColors.blue, textColor: BasicColors.white }, + { + backgroundColor: BasicColors.purple, + textColor: BasicColors.white, + }, + { + backgroundColor: BasicColors.magenta, + textColor: BasicColors.white, + }, + { + backgroundColor: BasicColors.violet, + textColor: BasicColors.white, + }, + { backgroundColor: BasicColors.gray, textColor: BasicColors.white }, + { + backgroundColor: BasicColors.silver, + textColor: BasicColors.black, + }, + ]; + super(clientId, _userInfo); + + this._color = cursorColors[BuiltInLiveCursor.currentColorIndex]; + + BuiltInLiveCursor.currentColorIndex++; + + if (BuiltInLiveCursor.currentColorIndex >= cursorColors.length) { + BuiltInLiveCursor.currentColorIndex = 0; + } + } +} diff --git a/packages/live-share-canvas/src/core/internals/ChangeLog.ts b/packages/live-share-canvas/src/core/internals/ChangeLog.ts new file mode 100644 index 000000000..6eebef412 --- /dev/null +++ b/packages/live-share-canvas/src/core/internals/ChangeLog.ts @@ -0,0 +1,48 @@ +import { IStroke } from "../Stroke.js"; +import { InkingManager } from "../InkingManager.js"; + +/** + * @internal + * Tracks stroke changes in {@link InkingManager} + */ +export class ChangeLog { + private _addedStrokes: Map = new Map(); + private _removedStrokes: Set = new Set(); + + public clear() { + this._addedStrokes.clear(); + this._removedStrokes.clear(); + } + + public mergeChanges(changes: ChangeLog) { + for (let id of changes._removedStrokes) { + if (!this._addedStrokes.delete(id)) { + this._removedStrokes.add(id); + } + } + + changes._addedStrokes.forEach((value: IStroke) => { + this._addedStrokes.set(value.id, value); + }); + } + + public addStroke(stroke: IStroke) { + this._addedStrokes.set(stroke.id, stroke); + } + + public removeStroke(id: string) { + this._removedStrokes.add(id); + } + + public getRemovedStrokes(): string[] { + return Array.from(this._removedStrokes); + } + + public getAddedStrokes(): IStroke[] { + return Array.from(this._addedStrokes.values()); + } + + get hasChanges(): boolean { + return this._addedStrokes.size > 0 || this._removedStrokes.size > 0; + } +} diff --git a/packages/live-share-canvas/src/core/internals/EphemeralCanvas.ts b/packages/live-share-canvas/src/core/internals/EphemeralCanvas.ts new file mode 100644 index 000000000..3bcfd7f81 --- /dev/null +++ b/packages/live-share-canvas/src/core/internals/EphemeralCanvas.ts @@ -0,0 +1,29 @@ +import { DryCanvas } from "../../canvas/index.js"; +import { InkingManager } from "../InkingManager.js"; + +/** + * @internal + * Used in {@link InkingManager} + */ +export class EphemeralCanvas extends DryCanvas { + private _removalTimeout?: number; + + constructor( + readonly clientId: string, + parentElement?: HTMLElement + ) { + super(parentElement); + } + + scheduleRemoval(onRemoveCallback: (canvas: EphemeralCanvas) => void) { + if (this._removalTimeout) { + window.clearTimeout(this._removalTimeout); + } + + this._removalTimeout = window.setTimeout(() => { + this.fadeOut(); + + onRemoveCallback(this); + }, InkingManager.ephemeralCanvasRemovalDelay); + } +} diff --git a/packages/live-share-canvas/src/core/internals/LiveCanvas-constants-internal.ts b/packages/live-share-canvas/src/core/internals/LiveCanvas-constants-internal.ts new file mode 100644 index 000000000..c5abe0031 --- /dev/null +++ b/packages/live-share-canvas/src/core/internals/LiveCanvas-constants-internal.ts @@ -0,0 +1,5 @@ +export enum InkingEventNames { + pointerMove = "PointerMove", + beginWetStroke = "BeginWetStroke", + addWetStrokePoints = "AddWetStrokePoint", +} diff --git a/packages/live-share-canvas/src/core/internals/LiveCanvas-interfaces-internal.ts b/packages/live-share-canvas/src/core/internals/LiveCanvas-interfaces-internal.ts new file mode 100644 index 000000000..5467a08f9 --- /dev/null +++ b/packages/live-share-canvas/src/core/internals/LiveCanvas-interfaces-internal.ts @@ -0,0 +1,10 @@ +import { IColor } from "../Colors.js"; + +export interface ISharedCursor { + isCursorShared?: boolean; +} + +export interface ICursorColor { + readonly backgroundColor: IColor; + readonly textColor: IColor; +} diff --git a/packages/live-share-canvas/src/core/internals/LiveCanvas-types-internal.ts b/packages/live-share-canvas/src/core/internals/LiveCanvas-types-internal.ts new file mode 100644 index 000000000..da59b42ab --- /dev/null +++ b/packages/live-share-canvas/src/core/internals/LiveCanvas-types-internal.ts @@ -0,0 +1,17 @@ +import { + IAddPointsEventArgs, + IBeginStrokeEventArgs, + IPointerMovedEventArgs, +} from "../InkingManager-interfaces.js"; +import { IEventUserInfo } from "../LiveCanvas-interfaces.js"; +import { ISharedCursor } from "./LiveCanvas-interfaces-internal.js"; + +export type IBeginWetStrokeEvent = IBeginStrokeEventArgs & + ISharedCursor & + IEventUserInfo; + +export type IAddWetStrokePointsEvent = IAddPointsEventArgs & + ISharedCursor & + IEventUserInfo; + +export type IPointerMovedEvent = IPointerMovedEventArgs & IEventUserInfo; diff --git a/packages/live-share-canvas/src/core/internals/LiveCanvasStorageSolution.ts b/packages/live-share-canvas/src/core/internals/LiveCanvasStorageSolution.ts new file mode 100644 index 000000000..df0b2738d --- /dev/null +++ b/packages/live-share-canvas/src/core/internals/LiveCanvasStorageSolution.ts @@ -0,0 +1,38 @@ +import { IEvent } from "@fluidframework/core-interfaces"; +import { TypedEventEmitter } from "@fluid-internal/client-utils"; +import { IStroke } from "../Stroke.js"; + +export enum StorageSolutionEvents { + strokeChanged = "strokeChanged", + strokeRemoved = "strokeRemoved", + strokesCleared = "strokesCleared", +} + +/** + * @hidden + */ +interface ILiveCanvasStorageSolutionEvents extends IEvent { + ( + event: StorageSolutionEvents.strokeChanged, + listener: (stroke: IStroke, local: boolean) => void + ): void; + ( + event: StorageSolutionEvents.strokeRemoved, + listener: (strokeId: IStroke, local: boolean) => void + ): void; + ( + event: StorageSolutionEvents.strokesCleared, + listener: (local: boolean) => void + ): void; +} + +export abstract class LiveCanvasStorageSolution extends TypedEventEmitter { + abstract forEach( + callbackfn: (value: IStroke, key: string) => void, + thisArg?: any + ): void; + abstract set(stroke: IStroke): void; + abstract delete(strokeId: string): void; + abstract clear(): void; + abstract dispose(): void; +} diff --git a/packages/live-share-canvas/src/core/internals/LivePointerInputProvider.ts b/packages/live-share-canvas/src/core/internals/LivePointerInputProvider.ts new file mode 100644 index 000000000..89f29d049 --- /dev/null +++ b/packages/live-share-canvas/src/core/internals/LivePointerInputProvider.ts @@ -0,0 +1,57 @@ +import { + IMulticastEvent, + IPointerEvent, + IPointerMoveEvent, + InputProvider, +} from "../../input/index.js"; + +/** + * @internal + * Decorator for InputProvider that ensures local user has correct + * roles before activating delegate input provider. + */ +export class LivePointerInputProvider extends InputProvider { + constructor( + private delegate: InputProvider, + private verifyLocalUserRoles: () => Promise + ) { + super(); + } + activate() { + this.verifyLocalUserRoles().then((allowed) => { + if (allowed) { + this.delegate.activate(); + } else { + this.delegate.deactivate(); + } + }); + } + + deactivate() { + this.delegate.deactivate(); + } + + get isActive(): boolean { + return this.delegate.isActive; + } + + get pointerDown(): IMulticastEvent { + return this.delegate.pointerDown; + } + + get pointerMove(): IMulticastEvent { + return this.delegate.pointerMove; + } + + get pointerUp(): IMulticastEvent { + return this.delegate.pointerUp; + } + + get pointerEnter(): IMulticastEvent { + return this.delegate.pointerEnter; + } + + get pointerLeave(): IMulticastEvent { + return this.delegate.pointerLeave; + } +} diff --git a/packages/live-share-canvas/src/core/internals/LiveStroke.ts b/packages/live-share-canvas/src/core/internals/LiveStroke.ts new file mode 100644 index 000000000..1d450605c --- /dev/null +++ b/packages/live-share-canvas/src/core/internals/LiveStroke.ts @@ -0,0 +1,73 @@ +import { IBrush } from "../Brush.js"; +import { IPointerPoint, getDistanceBetweenPoints } from "../Geometry.js"; +import { StrokeEndState } from "../InkingManager-constants.js"; +import { StrokeType } from "../Stroke.js"; + +/** + * @internal + */ +export class LiveStroke { + /** + * Configures the delay before wet stroke events are emitted, to greatly reduce the + * number of events emitted and improve performance. + */ + private static readonly wetStrokeEventsStreamDelay = 60; + + private _points: IPointerPoint[] = []; + private _processTimeout?: number; + + private process() { + if (this.type !== StrokeType.persistent) { + return; + } + + let index = 0; + + while (index + 2 < this._points.length) { + const p1 = this._points[index]; + const p2 = this._points[index + 1]; + const p3 = this._points[index + 2]; + + const p1p2 = getDistanceBetweenPoints(p1, p2); + const p2p3 = getDistanceBetweenPoints(p2, p3); + const p1p3 = getDistanceBetweenPoints(p1, p3); + + const threshold = (p1p2 + p2p3) * (100 / p1p3); + + if (threshold < this.simplificationThreshold) { + this._points.splice(index + 1, 1); + } else { + index++; + } + } + } + + endState?: StrokeEndState; + + constructor( + readonly id: string, + readonly type: StrokeType, + readonly brush: IBrush, + readonly simplificationThreshold: number + ) {} + + get points(): IPointerPoint[] { + return this._points; + } + + clear() { + this._points = []; + } + + scheduleProcessing(onProcessedCallback: (stroke: LiveStroke) => void) { + if (this._processTimeout === undefined) { + this._processTimeout = window.setTimeout(() => { + this.process(); + + this._processTimeout = undefined; + + onProcessedCallback(this); + }, LiveStroke.wetStrokeEventsStreamDelay); + } + } +} diff --git a/packages/live-share-canvas/src/core/internals/SharedMapStorageSolution.ts b/packages/live-share-canvas/src/core/internals/SharedMapStorageSolution.ts new file mode 100644 index 000000000..f21e6a4c7 --- /dev/null +++ b/packages/live-share-canvas/src/core/internals/SharedMapStorageSolution.ts @@ -0,0 +1,85 @@ +import { + ISequencedDocumentMessage, + IValueChanged, + SharedMap, +} from "fluid-framework/legacy"; +import { + LiveCanvasStorageSolution, + StorageSolutionEvents, + isClearEvent, +} from "./index.js"; +import { IStroke, Stroke } from "../Stroke.js"; +import { InkingManager } from "../InkingManager.js"; + +export class SharedMapStorageSolution extends LiveCanvasStorageSolution { + private registeredListeners = new Map(); + constructor( + private dryInkMap: SharedMap, + private inkingManager: InkingManager + ) { + super(); + this.setupListeners(); + } + + setupListeners() { + const valueChangedListener = ( + changed: IValueChanged, + local: boolean + ) => { + const serializedStroke: string | undefined = this.dryInkMap.get( + changed.key + ); + if (serializedStroke) { + const stroke = + this.inkingManager.getStroke(changed.key) ?? new Stroke(); + stroke.deserialize(serializedStroke); + this.emit(StorageSolutionEvents.strokeChanged, stroke, local); + } else { + this.emit( + StorageSolutionEvents.strokeRemoved, + changed.key, + local + ); + } + }; + this.registeredListeners.set("valueChanged", valueChangedListener); + this.dryInkMap.on("valueChanged", valueChangedListener); + const opListener = ( + op: ISequencedDocumentMessage, + local: boolean + ): void => { + if (isClearEvent(op.contents)) { + this.emit(StorageSolutionEvents.strokesCleared, local); + } + }; + this.registeredListeners.set("op", opListener); + this.dryInkMap.on("op", opListener); + } + + forEach( + callbackfn: (value: IStroke, key: string) => void, + thisArg?: any + ): void { + // Setup incoming dry ink changes + this.dryInkMap.forEach((value: string) => { + const stroke = new Stroke(); + stroke.deserialize(value); + + callbackfn(stroke, stroke.id); + }); + } + set(stroke: IStroke): void { + this.dryInkMap.set(stroke.id, stroke.serialize()); + } + delete(strokeId: string): void { + this.dryInkMap.delete(strokeId); + } + clear(): void { + this.dryInkMap.clear(); + } + dispose(): void { + this.registeredListeners.forEach((listener, key) => { + this.dryInkMap.off(key as any, listener as any); + }); + } +} diff --git a/packages/live-share-canvas/src/core/internals/SharedTreeStorageSolution.ts b/packages/live-share-canvas/src/core/internals/SharedTreeStorageSolution.ts new file mode 100644 index 000000000..591f9213e --- /dev/null +++ b/packages/live-share-canvas/src/core/internals/SharedTreeStorageSolution.ts @@ -0,0 +1,195 @@ +import { IStroke } from "../Stroke.js"; +import { + LiveCanvasStroke, + LiveCanvasTreeNode, +} from "../LiveCanvasTreeSchema.js"; +import { Tree, TreeStatus } from "fluid-framework"; +import { InkingManager } from "../InkingManager.js"; +import { LiveCanvasStorageSolution, StorageSolutionEvents } from "./index.js"; + +export class SharedTreeStorageSolution extends LiveCanvasStorageSolution { + private unsubscribeListeners: (() => void)[] = []; + // Track nodes previously checked so we can figure out which strokes were removed. + // This is needed because `Tree.on` doesn't include a diff of changes. + private previousCheckedNodes: Map = new Map(); + // Map to track some metadata about strokes we have already rendered. + // This helps us skip rendering strokes / updates that haven't changed. + private renderedStrokesMap: Map< + string, + { + timestamp: number; + status: TreeStatus; + } + > = new Map(); + + constructor( + private root: LiveCanvasTreeNode, + private inkingManager: InkingManager + ) { + super(); + // Start listening for changes to the strokes map and its child nodes + this.setupListeners(); + } + + private setupListeners(checkForChanges: boolean = false) { + // Unsubscribe to existing listeners + this.unsubscribeListeners.forEach((unsubscribe) => unsubscribe()); + + // Listen for changes to the stroke map + const unsubscribe = Tree.on(this.root.dryInkMap, "nodeChanged", () => { + // Fluid currently doesn't expose what keys were added/updated/removed. + // Thus, we just brute force our way through it and re-listen to everything. + // This time, we want to emit changes to `LiveCanvas`, so we set `checkForChanges` to true. + this.setupListeners(true); + }); + this.unsubscribeListeners = [unsubscribe]; + + // If we are checking for changes, we want to first check if the map is empty. + // If it is and we have currently rendered strokes, we emit a clear event. + if (checkForChanges) { + if (this.root.dryInkMap.size === 0) { + if (this.renderedStrokesMap.size === 0) { + // There is no change to what has been rendered. + // This includes cases where the local user was the one to clear the strokes. + // `InkingManager` optimistically clears stuff before emitting it. + // Thus, we can safely skip emitting this back to `LiveCanvas`. + return; + } + // Clear all rendered strokes, since we are clearing the `InkingManager`. + this.renderedStrokesMap.clear(); + + // Notify `LiveCanvas` that the strokes were cleared. + // Hardcode to false because the local client should never have initiated this. + // If they did, it would have been because of undo/redo, merge resolution, or something else. + // In that case, its fine to treat the change like we do for remote clients. + this.emit(StorageSolutionEvents.strokesCleared, false); + return; + } + } + // Track strokes currently in map so we can set into this.previousCheckedNodes after we notify of removed nodes + const newCheckedNodes: Map = new Map(); + + // Iterate through each stroke node and listen for changes to them + this.root.dryInkMap.forEach((value, key) => { + // We checked this node, any leftovers we will notify that the node was removed + this.previousCheckedNodes.delete(key); + newCheckedNodes.set(key, value); + // Listen for changes to the strokes + const nodeUnsubscribe = Tree.on(value, "treeChanged", () => { + // Emit change to `LiveCanvas` + this.handleNewOrChangedStroke(value, Tree.status(value)); + }); + this.unsubscribeListeners.push(nodeUnsubscribe); + + if (!checkForChanges) return; + + // Check for existing timestamp + const lastState = this.renderedStrokesMap.get(key); + const status = Tree.status(value); + // Check if we have already rendered the change. If so, skip. + if ( + lastState?.timestamp === value.timestamp && + lastState?.status === status + ) + return; + + // Emit the changed stroke to `LiveCanvas` + this.handleNewOrChangedStroke(value, status); + }); + + // Any unchecked nodes are no longer in dryStrokeMap, so we notify they were removed + this.previousCheckedNodes.forEach((value) => { + // Set the stroke as rendered + this.renderedStrokesMap.set(value.id, { + timestamp: value.timestamp, + status: Tree.status(value), + }); + // We need to remove the node from `InkingManager` so we notify `LiveCanvas` that it was removed. + this.emit(StorageSolutionEvents.strokeRemoved, value.id, false); + }); + // Set the most recent checked nodes as previous for susequent change comparisons + this.previousCheckedNodes = newCheckedNodes; + } + + forEach( + callbackfn: (value: IStroke, key: string) => void, + thisArg?: any + ): void { + this.root.dryInkMap.forEach((value, key) => { + const stroke = value.deserialize(); + this.renderedStrokesMap.set(value.id, { + timestamp: value.timestamp, + status: Tree.status(value), + }); + callbackfn(stroke, key); + }); + } + + set(stroke: IStroke): void { + // We will have already rendered the change locally, so we set it as rendered + this.renderedStrokesMap.set(stroke.id, { + timestamp: stroke.timeStamp, + status: TreeStatus.InDocument, + }); + // If the node already exists in the map, update changable values rather than replace the node + const existingNode = this.root.dryInkMap.get(stroke.id); + if (existingNode) { + // TODO: down the road, it would be good to only update the values that changed + Tree.runTransaction(existingNode, () => { + existingNode.points = stroke.serializePoints(); + existingNode.timestamp = stroke.timeStamp; + existingNode.version = stroke.version; + existingNode.clientId = stroke.clientId; + existingNode.brush.type = stroke.brush.type; + existingNode.brush.tipSize = stroke.brush.tipSize; + existingNode.brush.tip = stroke.brush.tip; + existingNode.brush.endArrow = stroke.brush.endArrow; + existingNode.brush.color.r = stroke.brush.color.r; + existingNode.brush.color.g = stroke.brush.color.g; + existingNode.brush.color.b = stroke.brush.color.b; + }); + return; + } + // Set the new stroke to the map + this.root.dryInkMap.set(stroke.id, LiveCanvasStroke.fromStroke(stroke)); + } + delete(strokeId: string): void { + const stroke = this.root.dryInkMap.get(strokeId); + if (!stroke) return; + // We will have already rendered the change locally, so we set it as rendered + this.renderedStrokesMap.set(stroke.id, { + timestamp: stroke.timestamp, + status: TreeStatus.Removed, + }); + this.root.dryInkMap.delete(stroke.id); + } + clear(): void { + // We will have already rendered the change locally, so we clear it + this.renderedStrokesMap.clear(); + // Delete all strokes in the map + this.root.dryInkMap.clear(); + } + dispose(): void { + // Unsubscribe to listeners + this.unsubscribeListeners.forEach((unsubscribe) => unsubscribe()); + // Reset rendered strokes and previously checked nodes + this.renderedStrokesMap.clear(); + this.previousCheckedNodes.clear(); + } + + private handleNewOrChangedStroke( + stroke: LiveCanvasStroke, + status: TreeStatus + ) { + // Mark the change as rendered + this.renderedStrokesMap.set(stroke.id, { + timestamp: stroke.timestamp, + status, + }); + // Update the existing stroke or create a new one + const existingStroke = this.inkingManager.getStroke(stroke.id); + const strokeToEmit = stroke.deserialize(existingStroke); + // Emit the stroke to `LiveCanvas` + this.emit(StorageSolutionEvents.strokeChanged, strokeToEmit, false); + } +} diff --git a/packages/live-share-canvas/src/core/internals/WetStroke.ts b/packages/live-share-canvas/src/core/internals/WetStroke.ts new file mode 100644 index 000000000..ae0e93cad --- /dev/null +++ b/packages/live-share-canvas/src/core/internals/WetStroke.ts @@ -0,0 +1,163 @@ +import { + IStrokeCreationOptions, + Stroke, + StrokeMode, + StrokeType, +} from "../Stroke.js"; +import { InkingCanvas } from "../../canvas/index.js"; +import { IWetStroke } from "../InkingManager-interfaces.js"; +import { IPointerPoint } from "../Geometry.js"; +import { computeEndArrow } from "./utils.js"; + +/** + * @internal + */ +export abstract class WetStroke extends Stroke implements IWetStroke { + protected notifyStrokeEnded(isCancelled: boolean) { + if (this.onStrokeEnded) { + this.onStrokeEnded(this, isCancelled); + } + } + + onStrokeEnded?: (sender: WetStroke, isCancelled: boolean) => void; + + constructor( + private _canvas: InkingCanvas, + readonly type: StrokeType, + readonly mode: StrokeMode, + options?: IStrokeCreationOptions + ) { + super(options); + + this._canvas.setBrush(this.brush); + } + + straighten(p: IPointerPoint): IPointerPoint { + return p; + } + + end() { + this._canvas.removeFromDOM(); + this._canvas.endStroke(); + + this.notifyStrokeEnded(false); + } + + cancel() { + this._canvas.removeFromDOM(); + this._canvas.cancelStroke(); + + this.notifyStrokeEnded(true); + } + + get canvas(): InkingCanvas { + return this._canvas; + } +} + +export class WetFreehandStroke extends WetStroke { + addPoints(...points: IPointerPoint[]): boolean { + const currentLength = this.length; + const result = super.addPoints(...points); + + if (result) { + let startIndex = currentLength; + + if (startIndex === 0) { + this.canvas.beginStroke(this.getPointAt(0)); + + startIndex = 1; + } + + for (let i = startIndex; i < this.length; i++) { + this.canvas.addPoint(this.getPointAt(i)); + } + } + + return result; + } + + end() { + if (this.length > 1 && this.brush.endArrow === "open") { + const penultimatePoint = this.getPointAt(this.length - 2); + const lastPoint = this.getPointAt(this.length - 1); + + const arrowPath = computeEndArrow(penultimatePoint, lastPoint); + + for (let i = 0; i < arrowPath.length; i++) { + const p = { ...arrowPath[i], pressure: lastPoint.pressure }; + + this.addPoint(p); + } + } + + super.end(); + } +} + +/** + * @internal + */ +export class WetLineStroke extends WetStroke { + straighten(p: IPointerPoint): IPointerPoint { + const result = { ...p }; + + if (this.length > 0) { + const firstPoint = this.getPointAt(0); + + if ( + Math.abs(result.x - firstPoint.x) > + Math.abs(result.y - firstPoint.y) + ) { + result.y = firstPoint.y; + } else { + result.x = firstPoint.x; + } + } + + return result; + } + + addPoints(...points: IPointerPoint[]): boolean { + if (this.length === 0) { + this.addPoint(points[0]); + + if (points.length > 1) { + this.addPoint(points[points.length - 1]); + } + } else { + const firstPoint = this.getPointAt(0); + + this.clear(); + + this.addPoint(firstPoint); + this.addPoint(points[points.length - 1]); + } + + this.canvas.cancelStroke(); + this.canvas.beginStroke(this.getPointAt(0)); + + if (this.length > 1) { + this.canvas.addPoint(this.getPointAt(1)); + + if (this.brush.endArrow === "open") { + const arrowPath = computeEndArrow( + this.getPointAt(0), + this.getPointAt(1) + ); + + for (let i = 0; i < arrowPath.length; i++) { + const p = { + ...arrowPath[i], + pressure: this.getPointAt(1).pressure, + }; + + this.addPoint(p); + this.canvas.addPoint(p); + } + } + } + + return true; + } +} diff --git a/packages/live-share-canvas/src/core/internals/index.ts b/packages/live-share-canvas/src/core/internals/index.ts index ebc202768..6fe42ffb9 100644 --- a/packages/live-share-canvas/src/core/internals/index.ts +++ b/packages/live-share-canvas/src/core/internals/index.ts @@ -1,2 +1,15 @@ -export * from "./TelemetryEvents"; -export * from "./utils"; +export * from "./TelemetryEvents.js"; +export * from "./utils.js"; +export * from "./ChangeLog.js"; +export * from "./EphemeralCanvas.js"; +export * from "./WetStroke.js"; +export * from "./LiveCanvas-types-internal.js"; +export * from "./LiveCanvas-constants-internal.js"; +export * from "./LiveCanvas-interfaces-internal.js"; +export * from "./LiveStroke.js"; +export * from "./BuiltInLiveCursor.js"; +export * from "./LivePointerInputProvider.js"; +export * from "./LiveCanvasStorageSolution.js"; +export * from "./SharedMapStorageSolution.js"; +export * from "./SharedTreeStorageSolution.js"; +export * from "./undo-redo-utils.js"; diff --git a/packages/live-share-canvas/src/core/internals/undo-redo-utils.ts b/packages/live-share-canvas/src/core/internals/undo-redo-utils.ts new file mode 100644 index 000000000..be132f67c --- /dev/null +++ b/packages/live-share-canvas/src/core/internals/undo-redo-utils.ts @@ -0,0 +1,87 @@ +import { + CommitKind, + CommitMetadata, + Listenable, + Revertible, + RevertibleFactory, + TreeViewEvents, +} from "fluid-framework"; + +/** + * Create undo and redo stacks for a tree view. The stacks are populated with revertible objects. + * You can manage the stacks by calling `undo` and `redo`. The redo stack is cleared when a new commit is made. + * The dispose function should be called when the stacks are no longer needed. + */ +export function createUndoRedoStacks( + events: Listenable +): undoRedo { + // Create arrays to store revertible objects + const undoStack: Revertible[] = []; + const redoStack: Revertible[] = []; + + // Manage the stacks when a new commit is made + function onNewCommit( + commit: CommitMetadata, + getRevertible?: RevertibleFactory + ): void { + if (getRevertible === undefined) { + return; + } + const revertible = getRevertible(); + if (commit.kind === CommitKind.Undo) { + redoStack.push(revertible); + } else { + if (commit.kind === CommitKind.Default) { + // clear redo stack + for (const redo of redoStack) { + redo.dispose(); + } + redoStack.length = 0; + } + undoStack.push(revertible); + } + } + + // Subscribe to the commitApplied event + const unsubscribeFromCommitApplied = events.on( + "commitApplied", + onNewCommit + ); + + // Dispose function to clean up the stacks + const dispose = () => { + unsubscribeFromCommitApplied(); + for (const revertible of undoStack) { + revertible.dispose(); + } + for (const revertible of redoStack) { + revertible.dispose(); + } + redoStack.length = 0; + undoStack.length = 0; + }; + + // Function to revert from a stack + function revertFromStack(stack: Revertible[]): void { + const revertible = stack.pop(); + if (revertible !== undefined) { + revertible.revert(); + } + } + + function undo(): void { + revertFromStack(undoStack); + } + + function redo(): void { + revertFromStack(redoStack); + } + + return { undo, redo, dispose }; +} + +export type undoRedo = { + undo: () => void; + redo: () => void; + dispose: () => void; +}; diff --git a/packages/live-share-canvas/src/core/internals/utils.ts b/packages/live-share-canvas/src/core/internals/utils.ts index c2e8842ad..5e460867f 100644 --- a/packages/live-share-canvas/src/core/internals/utils.ts +++ b/packages/live-share-canvas/src/core/internals/utils.ts @@ -5,6 +5,7 @@ import { v4 as uuid } from "uuid"; import { BrushTipShape, + ClearEvent, IColor, IPoint, IPointerPoint, @@ -12,7 +13,7 @@ import { ISegment, getPressureAdjustedSize, toCssRgbaColor, -} from ".."; +} from "../index.js"; /** * Pre-calculated Pi x 2. @@ -20,6 +21,8 @@ import { export const TWO_PI: number = Math.PI * 2; const EPSILON = 0.000001; +const UNSAFE_HTML_URI_CHARACTERS = /[<>"'`]/; +const SAFE_IMAGE_URL_PROTOCOLS = new Set(["http:", "https:"]); /** * Generates a unique Id. @@ -62,6 +65,47 @@ export function forceIntoRange(n: number, min: number, max: number): number { return n; } +/** + * Validates a user profile image URL before it is transmitted or rendered. + * Returns `undefined` when the value is empty, malformed, or uses an unsafe scheme. + */ +export function sanitizeUserPictureUrl( + pictureUri?: string +): string | undefined { + if (!pictureUri) { + return undefined; + } + + const trimmedPictureUri = pictureUri.trim(); + + if ( + trimmedPictureUri.length === 0 || + UNSAFE_HTML_URI_CHARACTERS.test(trimmedPictureUri) + ) { + return undefined; + } + + let parsedUrl: URL; + + try { + parsedUrl = new URL(trimmedPictureUri); + } catch { + return undefined; + } + + const protocol = parsedUrl.protocol.toLowerCase(); + + if (!SAFE_IMAGE_URL_PROTOCOLS.has(protocol)) { + return undefined; + } + + if (parsedUrl.username || parsedUrl.password) { + return undefined; + } + + return parsedUrl.href; +} + /** * @hidden * Defines a quad, i.e. a polygon with 4 sides. @@ -295,7 +339,9 @@ export function renderFilledSVGCircle( color: IColor ): string { // eslint-disable-next-line prettier/prettier - return ``; + return ``; } /** @@ -652,3 +698,15 @@ export function computeEndArrow( }, ]; } + +/** + * Type guard that checks if a Fluid op is of type {@link ClearEvent} + */ +export function isClearEvent(value: any): boolean { + return ( + typeof value === "object" && + typeof value.type === "string" && + // Fluid v2 emits "clear" instead of "Clear" on SharedMap.clear(), so we equalize it + value.type.toLowerCase() === ClearEvent.toLowerCase() + ); +} diff --git a/packages/live-share-canvas/src/index.ts b/packages/live-share-canvas/src/index.ts index d65a0766a..fd5d8c91e 100644 --- a/packages/live-share-canvas/src/index.ts +++ b/packages/live-share-canvas/src/index.ts @@ -3,6 +3,6 @@ * Licensed under the Microsoft Live Share SDK License. */ -export * from "./core"; -export * from "./canvas"; -export * from "./input"; +export * from "./core/index.js"; +export * from "./canvas/index.js"; +export * from "./input/index.js"; diff --git a/packages/live-share-canvas/src/input/InputFilter.ts b/packages/live-share-canvas/src/input/InputFilter.ts index bc9ec67d8..39c6f01f0 100644 --- a/packages/live-share-canvas/src/input/InputFilter.ts +++ b/packages/live-share-canvas/src/input/InputFilter.ts @@ -3,7 +3,7 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { IPointerPoint } from "../core"; +import { IPointerPoint } from "../core/index.js"; /** * Defines an input filter. Input filters are used to transform diff --git a/packages/live-share-canvas/src/input/InputProvider.ts b/packages/live-share-canvas/src/input/InputProvider.ts index 35ceabdc0..e4b288460 100644 --- a/packages/live-share-canvas/src/input/InputProvider.ts +++ b/packages/live-share-canvas/src/input/InputProvider.ts @@ -3,7 +3,7 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { IPointerPoint } from "../core"; +import { IPointerPoint } from "../core/index.js"; /** * Represents a pointer event such as up, down or enter. diff --git a/packages/live-share-canvas/src/input/JitterFilter.ts b/packages/live-share-canvas/src/input/JitterFilter.ts index dcedd7c6e..b238bf8b8 100644 --- a/packages/live-share-canvas/src/input/JitterFilter.ts +++ b/packages/live-share-canvas/src/input/JitterFilter.ts @@ -3,8 +3,8 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { InputFilter } from "./InputFilter"; -import { IPointerPoint } from "../core"; +import { InputFilter } from "./InputFilter.js"; +import { IPointerPoint } from "../core/index.js"; /** * Implements a jitter reduction filter, which straightens stroke by ignoring diff --git a/packages/live-share-canvas/src/input/PointerInputProvider.ts b/packages/live-share-canvas/src/input/PointerInputProvider.ts index f191f9aac..f451ff2cf 100644 --- a/packages/live-share-canvas/src/input/PointerInputProvider.ts +++ b/packages/live-share-canvas/src/input/PointerInputProvider.ts @@ -3,7 +3,7 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { InputProvider, IPointerEvent } from "./InputProvider"; +import { InputProvider, IPointerEvent } from "./InputProvider.js"; function pointerEventToIPointerEvent(e: PointerEvent): IPointerEvent { return { diff --git a/packages/live-share-canvas/src/input/index.ts b/packages/live-share-canvas/src/input/index.ts index af255929a..358009d33 100644 --- a/packages/live-share-canvas/src/input/index.ts +++ b/packages/live-share-canvas/src/input/index.ts @@ -3,7 +3,7 @@ * Licensed under the Microsoft Live Share SDK License. */ -export * from "./InputFilter"; -export * from "./InputProvider"; -export * from "./JitterFilter"; -export * from "./PointerInputProvider"; +export * from "./InputFilter.js"; +export * from "./InputProvider.js"; +export * from "./JitterFilter.js"; +export * from "./PointerInputProvider.js"; diff --git a/packages/live-share-canvas/src/test/Miscellaneous.spec.ts b/packages/live-share-canvas/src/test/Miscellaneous.spec.ts index ef1761b4f..6b5cf54df 100644 --- a/packages/live-share-canvas/src/test/Miscellaneous.spec.ts +++ b/packages/live-share-canvas/src/test/Miscellaneous.spec.ts @@ -10,15 +10,15 @@ import { screenToViewport, viewportToScreen, ISegment, -} from "../core"; -import { assertObjectsEqual } from "./Utils.spec"; +} from "../core/index.js"; +import { assertObjectsEqual } from "./Utils.spec.js"; import { doRectanglesOverlap, getSegmentsIntersection, isPointInsideRectangle, isRectangleInsideRectangle, segmentsMayIntersect, -} from "../core/internals"; +} from "../core/internals/index.js"; const testColor: IColor = { r: 193, g: 221, b: 202 }; const serializedTestColor = "#C1DDCA"; diff --git a/packages/live-share-canvas/src/test/Security.spec.ts b/packages/live-share-canvas/src/test/Security.spec.ts new file mode 100644 index 000000000..dcd6b462f --- /dev/null +++ b/packages/live-share-canvas/src/test/Security.spec.ts @@ -0,0 +1,135 @@ +import "mocha"; +import { strict as assert } from "assert"; +import { + BuiltInLiveCursor, + sanitizeUserPictureUrl, +} from "../core/internals/index.js"; + +class MockElement { + public readonly children: MockElement[] = []; + public readonly attributes = new Map(); + public readonly style: Record = {}; + public textContent = ""; + + constructor(public readonly tagName: string) {} + + appendChild(child: T): T { + this.children.push(child); + + return child; + } + + setAttribute(name: string, value: string): void { + this.attributes.set(name, value); + } +} + +class MockDocument { + createElement(tagName: string): MockElement { + return new MockElement(tagName); + } + + createElementNS(_namespace: string, tagName: string): MockElement { + return new MockElement(tagName); + } +} + +function findElementsByTagName( + root: MockElement, + tagName: string +): MockElement[] { + const matches: MockElement[] = []; + + if (root.tagName === tagName) { + matches.push(root); + } + + for (const child of root.children) { + matches.push(...findElementsByTagName(child, tagName)); + } + + return matches; +} + +describe("Security", () => { + it("rejects URLs with embedded credentials", async () => { + assert.equal( + sanitizeUserPictureUrl("https://user:pass@contoso.com/avatar.png"), + undefined + ); + }); + + it("rejects URLs with username only", async () => { + assert.equal( + sanitizeUserPictureUrl("https://user@contoso.com/avatar.png"), + undefined + ); + }); + + it("sanitizes picture URLs before they are rendered or transmitted", async () => { + assert.equal( + sanitizeUserPictureUrl("https://contoso.com/avatar.png"), + "https://contoso.com/avatar.png" + ); + assert.equal( + sanitizeUserPictureUrl("javascript:alert('xss')"), + undefined + ); + assert.equal( + sanitizeUserPictureUrl( + // eslint-disable-next-line no-useless-escape + 'https://contoso.com/avatar.png\" onerror=\"alert(1)' + ), + undefined + ); + assert.equal(sanitizeUserPictureUrl("not a url"), undefined); + }); + + it("renders built-in cursors without using HTML parsing", async () => { + const originalDocument = globalThis.document; + const mockDocument = new MockDocument() as unknown as Document; + + (globalThis as typeof globalThis & { document: Document }).document = + mockDocument; + + try { + const cursor = new BuiltInLiveCursor("client-id", { + displayName: '', + pictureUri: "https://contoso.com/avatar.png", + }); + + const renderedElement = + cursor.renderedElement as unknown as MockElement; + const imageElements = findElementsByTagName(renderedElement, "img"); + const pathElements = findElementsByTagName(renderedElement, "path"); + const nameElement = findElementsByTagName( + renderedElement, + "div" + ).find( + (element) => + element.textContent === '' + ); + + assert.equal(imageElements.length, 1); + assert.equal( + imageElements[0].attributes.get("src"), + "https://contoso.com/avatar.png" + ); + assert.equal(imageElements[0].attributes.get("alt"), ""); + assert.equal( + imageElements[0].attributes.get("aria-hidden"), + "true" + ); + assert.equal(pathElements.length, 2); + assert.ok(nameElement); + } finally { + if (originalDocument) { + ( + globalThis as typeof globalThis & { document: Document } + ).document = originalDocument; + } else { + delete (globalThis as Partial).document; + } + } + }); +}); diff --git a/packages/live-share-canvas/src/test/Stroke.spec.ts b/packages/live-share-canvas/src/test/Stroke.spec.ts index bb1183c83..01f0f8b91 100644 --- a/packages/live-share-canvas/src/test/Stroke.spec.ts +++ b/packages/live-share-canvas/src/test/Stroke.spec.ts @@ -1,12 +1,12 @@ import "mocha"; import { strict as assert } from "assert"; -import { Stroke } from "../core/Stroke"; +import { Stroke } from "../core/Stroke.js"; import { assertPointArraysEqual, copyPointArrayAndDuplidateEachPoint, reducePointArrayPrecision, -} from "./Utils.spec"; -import { IPointerPoint } from "../core"; +} from "./Utils.spec.js"; +import { IPointerPoint } from "../core/index.js"; const testPoints: IPointerPoint[] = [ { diff --git a/packages/live-share-canvas/src/test/Utils.spec.ts b/packages/live-share-canvas/src/test/Utils.spec.ts index 76f00e970..c851e1f2f 100644 --- a/packages/live-share-canvas/src/test/Utils.spec.ts +++ b/packages/live-share-canvas/src/test/Utils.spec.ts @@ -1,6 +1,6 @@ import "mocha"; import { strict as assert } from "assert"; -import { Stroke, IPointerPoint, IColor, IRect } from "../core"; +import { Stroke, IPointerPoint, IColor, IRect } from "../core/index.js"; export const coordinateSerializationPrecision = Stroke[ "coordinateSerializationPrecision" @@ -71,8 +71,10 @@ export function assertObjectsEqual( const propertyNames = Object.getOwnPropertyNames(expected); for (const p of propertyNames) { + const expectedCast = expected as any; + const actualCast = actual as any; assert( - expected[p] === actual[p], + expectedCast[p] === actualCast[p], errorMessage + ` (expected = ${JSON.stringify( expected diff --git a/packages/live-share-canvas/tsconfig.build.json b/packages/live-share-canvas/tsconfig.build.json deleted file mode 100644 index 9d8cab4a6..000000000 --- a/packages/live-share-canvas/tsconfig.build.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ - }, - "exclude": [ - "test/**/*.ts" - ] - } \ No newline at end of file diff --git a/packages/live-share-canvas/tsconfig.json b/packages/live-share-canvas/tsconfig.json index 258994400..f1195380b 100644 --- a/packages/live-share-canvas/tsconfig.json +++ b/packages/live-share-canvas/tsconfig.json @@ -1,76 +1,66 @@ { - "compilerOptions": { - /* Visit https://aka.ms/tsconfig.json to read more about this file */ - - /* Basic Options */ - // "incremental": true, /* Enable incremental compilation */ - "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ - "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ - "lib": ["es2020","DOM"], /* Specify library files to be included in the compilation. */ - "allowJs": false, /* Allow javascript files to be compiled. */ - // "checkJs": true, /* Report errors in .js files. */ - // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ - "declaration": true, /* Generates corresponding '.d.ts' file. */ - "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ - "sourceMap": true, /* Generates corresponding '.map' file. */ - // "outFile": "./", /* Concatenate and emit output to single file. */ - "outDir": "./bin", /* Redirect output structure to the directory. */ - // "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ - // "composite": true, /* Enable project compilation */ - // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ - // "removeComments": true, /* Do not emit comments to output. */ - // "noEmit": true, /* Do not emit outputs. */ - // "importHelpers": true, /* Import emit helpers from 'tslib'. */ - // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ - // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ - - /* Strict Type-Checking Options */ - "strict": true, /* Enable all strict type-checking options. */ - // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* Enable strict null checks. */ - // "strictFunctionTypes": true, /* Enable strict checking of function types. */ - // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ - // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ - // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ - // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ - - /* Additional Checks */ - // "noUnusedLocals": true, /* Report errors on unused locals. */ - // "noUnusedParameters": true, /* Report errors on unused parameters. */ - // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ - // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - - /* Module Resolution Options */ - // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ - // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ - // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ - // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ - // "typeRoots": [], /* List of folders to include type definitions from. */ - // "types": [], /* Type declaration files to be included in compilation. */ - // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ - "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ - // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - - /* Source Map Options */ - // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ - // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ - - /* Experimental Options */ - // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ - // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ - - /* Advanced Options */ - "skipLibCheck": true, /* Skip type checking of declaration files. */ - "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ - }, - "exclude": ["build", "dist", "node_modules"], - "include": [ - "test/**/*.ts" - ], - "files": [ - "src/index.ts" - ] + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + /* Basic Options */ + // "incremental": true, /* Enable incremental compilation */ + "target": "ES2022" /* Specify ECMAScript target version. */, + "module": "Node16" /* Specify module code generation. */, + "lib": [ + "ES2022", + "DOM" + ] /* Specify library files to be included in the compilation. */, + "allowJs": false /* Allow javascript files to be compiled. */, + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + "declaration": true /* Generates corresponding '.d.ts' file. */, + "declarationMap": true /* Generates a sourcemap for each corresponding '.d.ts' file. */, + "sourceMap": true /* Generates corresponding '.map' file. */, + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "./bin/esm" /* Redirect output structure to the directory. */, + // "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + /* Strict Type-Checking Options */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + /* Module Resolution Options */ + // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + /* Advanced Options */ + "skipLibCheck": true /* Skip type checking of declaration files. */, + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + }, + "files": ["src/index.ts"] } diff --git a/packages/live-share-canvas/tsconfig.test.json b/packages/live-share-canvas/tsconfig.test.json new file mode 100644 index 000000000..398bdec25 --- /dev/null +++ b/packages/live-share-canvas/tsconfig.test.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./bin/test", + "types": ["mocha", "node"] + }, + "files": [], + "include": ["src/**/*"], + "exclude": [] +} diff --git a/packages/live-share-canvas/typedoc.json b/packages/live-share-canvas/typedoc.json deleted file mode 100644 index 098dacff3..000000000 --- a/packages/live-share-canvas/typedoc.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "entryPoints": ["./src/index.ts"], - "excludeExternals": true, - "excludePrivate": true, - "excludeInternal": true, - "name": "_microsoft_live_share_canvas", - "validation": { - "invalidLink": true - } -} diff --git a/packages/live-share-media/src/test/.mocharc.js b/packages/live-share-media/.mocharc.cjs similarity index 96% rename from packages/live-share-media/src/test/.mocharc.js rename to packages/live-share-media/.mocharc.cjs index 28b840eb9..49a4dd356 100644 --- a/packages/live-share-media/src/test/.mocharc.js +++ b/packages/live-share-media/.mocharc.cjs @@ -3,7 +3,7 @@ * Licensed under the Microsoft Live Share SDK License. */ -'use strict'; +"use strict"; const packageDir = `${__dirname}/../..`; diff --git a/packages/live-share-media/.nycrc.json b/packages/live-share-media/.nycrc.json index cc236d58b..ec2ba788b 100644 --- a/packages/live-share-media/.nycrc.json +++ b/packages/live-share-media/.nycrc.json @@ -8,4 +8,4 @@ "branches": 90, "functions": 95, "lines": 90 - } \ No newline at end of file +} diff --git a/packages/live-share-media/README.md b/packages/live-share-media/README.md index 4c8ed2dd8..1cc071add 100644 --- a/packages/live-share-media/README.md +++ b/packages/live-share-media/README.md @@ -35,15 +35,15 @@ This will use npm workspaces to hoist and build all dependencies. ```html - -
        - - - - -
        + +
        + + + + +
        ``` @@ -58,14 +58,12 @@ await microsoftTeams.app.initialize(); // Setup the Fluid container const host = LiveShareHost.create(); const client = new LiveShareClient(host); -const schema = { - initialObjects: { - mediaSession: LiveMediaSession, - ..., - }, -}; -const { container } = await client.joinContainer(schema); -const { mediaSession } = container.initialObjects; +await client.join(); + +const mediaSession = + (await client.getDDS) < + LiveMediaSession > + ("media-session-id", LiveMediaSession); // Get the player from your document and create synchronizer const player = document.getElementById("player"); @@ -78,21 +76,21 @@ await mediaSession.initialize(allowedRoles); // Intercept user play, pause, seek, and set track actions through synchronizer document.getElementById("play-button").onclick = () => { - synchronizer.play(); + synchronizer.play(); }; document.getElementById("pause-button").onclick = () => { - synchronizer.pause(); + synchronizer.pause(); }; document.getElementById("restart-button").onclick = () => { - synchronizer.seekTo(0); + synchronizer.seekTo(0); }; document.getElementById("change-track-button").onclick = () => { - synchronizer.setTrack({ - trackIdentifier: "SOME_OTHER_VIDEO_SRC", - }); + synchronizer.setTrack({ + trackIdentifier: "SOME_OTHER_VIDEO_SRC", + }); }; ``` @@ -102,7 +100,7 @@ There are several code samples that are hosted in a separate GitHub repository. | Sample name | Description | Javascript | | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- | -| React Video | Basic example showing how the LiveMediaSession object works with HTML5 video. | [View](https://aka.ms/liveshare-reactvideo) | +| React Video | Basic example showing how the LiveMediaSession object works with HTML5 video. | [View](https://aka.ms/liveshare-reactvideo) | | React Media Template | Enable all connected clients to watch videos together, build a shared playlist, transfer whom is in control, and annotate over the video. | [View](https://aka.ms/liveshare-mediatemplate) | ## Package Compatibility @@ -111,9 +109,10 @@ The Live Share SDK contains dependencies for [@microsoft/teams-js](https://www.n **It is critical that your app use the package dependencies listed in the table below.** Lookup the version of the `@microsoft/live-share` you're using and set any other dependencies in your package.json file to match: -| @microsoft/live-share | @microsoft/teams-js | fluid-framework | @microsoft/live-share-\* | @fluidframework/azure-client | @microsoft/TeamsFx | @microsoft/TeamsFx-react | -| --------------------- | -------------------- | --------------- | -------------------------- | ---------------------------- | ------------------------------- | ------------------------------- | -| ^1.0.0 | ^2.11.0 | ^1.2.3 | ^1.0.0 | ^1.0.0 | ^2.5.0 | ^2.5.0 | +| @microsoft/live-share | @microsoft/teams-js | fluid-framework | @microsoft/live-share-\* | @fluidframework/azure-client | @microsoft/TeamsFx | @microsoft/TeamsFx-react | +| --------------------- | ------------------- | --------------- | ------------------------ | ---------------------------- | ------------------ | ------------------------ | +| ^2.0.0 | ^2.11.0 | ^2.0.0 | ^2.0.0 | ^2.0.0 | ^2.5.0 | ^2.5.0 | +| ^1.0.0 | ^2.11.0 | ^1.2.3 | ^1.0.0 | ^1.0.0 | ^2.5.0 | ^2.5.0 | ## Contributing diff --git a/packages/live-share-media/package.json b/packages/live-share-media/package.json index 8de5a6a43..aa46753eb 100644 --- a/packages/live-share-media/package.json +++ b/packages/live-share-media/package.json @@ -1,37 +1,43 @@ { "name": "@microsoft/live-share-media", - "version": "1.4.0", + "version": "2.0.0-internal.18", "description": "Live Share classes that synchronize media playback across clients.", "author": "Microsoft", "license": "SEE LICENSE IN LICENSE", - "main": "./bin/index.js", - "types": "./bin/index.d.ts", + "type": "module", "scripts": { "clean": "npx shx rm -rf bin", - "build": "tsc -p tsconfig.build.json", - "test": "ts-mocha --config ./src/test/.mocharc.js src/**/*.spec.ts --timeout 10000", - "test:debug": "ts-mocha --config ./src/test/.mocharc.js src/**/*.spec.ts --inspect-brk", + "build": "node ../../internal/build-tools/build-package.js --esm", + "build:test": "node ../../internal/build-tools/build-package.js --test", + "test": "npm run build:test && mocha --config .mocharc.cjs --recursive \"./bin/test/**/*.spec.js\" --timeout 10000", + "test:debug": "npm run build:test && mocha --config .mocharc.cjs --recursive \"./bin/test/**/LiveMediaSession_Synchronizer.spec.js\" --inspect-brk", "test:coverage": "nyc --reporter=html --reporter=text --reporter=text-summary npm test", "test:race": "node ./../live-share/test-for-race-conditions.js" }, + "exports": { + "./package.json": "./package.json", + ".": { + "import": "./bin/esm/index.js" + } + }, "devDependencies": { - "@microsoft/live-share": "1.4.0", - "@fluidframework/test-client-utils": "^1.3.6", - "@fluidframework/test-runtime-utils": "^1.3.6", - "@fluidframework/test-utils": "^1.3.6", - "@fluidframework/test-version-utils": "^1.3.6", + "@fluidframework/mocha-test-setup": "^2.0.0-rc.1.0.9", + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", + "@fluidframework/test-utils": ">=2.40 <2.120", + "@live-share-private/test-utils": "^1.0.0", + "@microsoft/live-share": "2.0.0-internal.18", "@types/assert": "^1.5.6", "@types/mocha": "^10.0.1", "@types/node": "^20.2.3", - "fluid-framework": "^1.3.6", + "fluid-framework": ">=2.40 <2.120", "mocha": "^10.2.0", "nyc": "^15.1.0", "ts-mocha": "^10.0.0", - "typescript": "^5.0.4" + "typescript": "~5.5.3" }, "peerDependencies": { - "@microsoft/live-share": "1.4.0", - "fluid-framework": "^1.2.3" + "@microsoft/live-share": "2.0.0-internal.18", + "fluid-framework": ">=2.40 <2.120" }, "repository": { "directory": "packages/live-share-media", diff --git a/packages/live-share-media/src/LiveMediaSession.ts b/packages/live-share-media/src/LiveMediaSession.ts index b4b50e56d..e38c2565d 100644 --- a/packages/live-share-media/src/LiveMediaSession.ts +++ b/packages/live-share-media/src/LiveMediaSession.ts @@ -3,35 +3,39 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { DataObjectFactory } from "@fluidframework/aqueduct"; +import { DataObjectFactory } from "@fluidframework/aqueduct/legacy"; import { - DynamicObjectRegistry, - LiveDataObject, LiveDataObjectInitializeNotNeededError, LiveDataObjectInitializeState, LiveTelemetryLogger, UserMeetingRole, } from "@microsoft/live-share"; -import { MediaPlayerSynchronizer } from "./MediaPlayerSynchronizer"; -import { ITriggerActionEvent, TelemetryEvents } from "./internals"; +import { + DynamicObjectRegistry, + LiveDataObject, +} from "@microsoft/live-share/internal"; +import { MediaPlayerSynchronizer } from "./MediaPlayerSynchronizer.js"; +import { ITriggerActionEvent } from "./internals/GroupCoordinatorState.js"; import { MediaSessionCoordinatorEvents, ExtendedMediaSessionAction, ExtendedMediaSessionActionDetails, ExtendedMediaSessionActionHandler, -} from "./MediaSessionExtensions"; +} from "./MediaSessionExtensions.js"; import { LiveMediaSessionCoordinator, IMediaPlayerState, -} from "./LiveMediaSessionCoordinator"; -import { MediaSessionActionThrottler } from "./MediaSessionActionThrottler"; -import { RepeatedActionThrottler } from "./RepeatedActionThrottler"; -import { IMediaPlayer } from "./IMediaPlayer"; +} from "./LiveMediaSessionCoordinator.js"; +import { MediaSessionActionThrottler } from "./MediaSessionActionThrottler.js"; +import { RepeatedActionThrottler } from "./RepeatedActionThrottler.js"; +import { IMediaPlayer } from "./IMediaPlayer.js"; +import { SharedObjectKind } from "fluid-framework"; +import { TelemetryEvents } from "./internals/consts.js"; /** * Live fluid object that synchronizes media playback across multiple clients. */ -export class LiveMediaSession extends LiveDataObject { +export class LiveMediaSessionClass extends LiveDataObject { private _actionThrottler: MediaSessionActionThrottler = new RepeatedActionThrottler(); private _logger?: LiveTelemetryLogger; @@ -56,8 +60,8 @@ export class LiveMediaSession extends LiveDataObject { * The objects fluid type factory. */ public static readonly factory = new DataObjectFactory( - LiveMediaSession.TypeName, - LiveMediaSession, + LiveMediaSessionClass.TypeName, + LiveMediaSessionClass, [], {} ); @@ -341,7 +345,18 @@ export class LiveMediaSession extends LiveDataObject { } /** - * Register `LiveMediaSession` as an available `LoadableObjectClass` for use in packages that support dynamic object loading, such as `@microsoft/live-share-turbo`. + * Live fluid object that synchronizes media playback across multiple clients. + */ +export type LiveMediaSession = LiveMediaSessionClass; + +// eslint-disable-next-line no-redeclare +export const LiveMediaSession = (() => { + const kind = LiveMediaSessionClass; + return kind as typeof kind & SharedObjectKind; +})(); + +/** + * Register `LiveMediaSession` as an available `SharedObjectKind` for use in dynamic object loading. */ DynamicObjectRegistry.registerObjectClass( LiveMediaSession, diff --git a/packages/live-share-media/src/LiveMediaSessionCoordinator.ts b/packages/live-share-media/src/LiveMediaSessionCoordinator.ts index e26e68b6c..3fa6e8bf5 100644 --- a/packages/live-share-media/src/LiveMediaSessionCoordinator.ts +++ b/packages/live-share-media/src/LiveMediaSessionCoordinator.ts @@ -4,40 +4,46 @@ */ import { - LiveEventScope, LiveTelemetryLogger, - LiveEventTarget, - IRuntimeSignaler, TimeInterval, UserMeetingRole, - LiveShareRuntime, LiveDataObjectInitializeState, LiveDataObjectInitializeNotNeededError, LiveDataObjectNotInitializedError, - LiveObjectSynchronizer, ILiveEvent, } from "@microsoft/live-share"; +import { + IRuntimeSignaler, + LiveEventScope, + LiveEventTarget, + LiveObjectSynchronizer, + LiveShareRuntime, + isErrorLike, +} from "@microsoft/live-share/internal"; import { CoordinationWaitPoint, ExtendedMediaMetadata, ExtendedMediaSessionPlaybackState, MediaSessionCoordinatorSuspension, -} from "./MediaSessionExtensions"; +} from "./MediaSessionExtensions.js"; import { - TelemetryEvents, ITransportCommandEvent, ISetTrackEvent, IPositionUpdateEvent, GroupCoordinatorState, GroupCoordinatorStateEvents, ISetTrackDataEvent, + IRateChangeCommandEvent, +} from "./internals/GroupCoordinatorState.js"; +import { TelemetryEvents } from "./internals/consts.js"; +import { TrackMetadataNotSetError, ActionBlockedError, - IRateChangeCommandEvent, -} from "./internals"; -import { LiveMediaSessionCoordinatorSuspension } from "./LiveMediaSessionCoordinatorSuspension"; -import EventEmitter from "events"; -import { isErrorLike } from "@microsoft/live-share/bin/internals"; +} from "./internals/errors.js"; +import { PriorityTimeInterval } from "./internals/PriorityTimeInterval.js"; +import { LiveMediaSessionCoordinatorSuspension } from "./LiveMediaSessionCoordinatorSuspension.js"; +import { TypedEventEmitter } from "@fluid-internal/client-utils"; +import { IEvent } from "@fluidframework/core-interfaces"; /** * Most recent state of the media session. @@ -67,19 +73,51 @@ export interface IMediaPlayerState { positionState?: MediaPositionState; } +/** + * @hidden + */ +export interface ILiveMediaSessionCoordinatorEvents extends IEvent { + /** + * Event listener for events emitted + * @param event update + * @param listener listener function + * @param listener.event the event instance + */ + (event: string, listener: (event: any) => void): void; +} + /** * The `LiveMediaSessionCoordinator` tracks the playback & position state of all other * clients being synchronized with. It is responsible for keeping the local media player * in sync with the group. */ -export class LiveMediaSessionCoordinator extends EventEmitter { +export class LiveMediaSessionCoordinator extends TypedEventEmitter { private readonly _id: string; private readonly _runtime: IRuntimeSignaler; private readonly _liveRuntime: LiveShareRuntime; private readonly _logger: LiveTelemetryLogger; private readonly _getPlayerState: () => IMediaPlayerState; - private _positionUpdateInterval = new TimeInterval(2000); - private _maxPlaybackDrift = new TimeInterval(1000); + private _positionUpdateInterval = new PriorityTimeInterval( + 2000, + // Scale by function + () => { + const audience = this._liveRuntime.audience; + if (!audience) return 1; + // As the audience size gets bigger, we relax the update interval, since more variance is expected + const count = audience.getMembers().size; + return 1 + count / 5; + } + ); + private _maxPlaybackDrift = new PriorityTimeInterval( + 1500, // Scale by function + () => { + const audience = this._liveRuntime.audience; + if (!audience) return 1; + // As the audience size gets bigger, we relax the playback drift, since more variance is expected + const count = audience.getMembers().size; + return 1 + count / 25; + } + ); private _lastWaitPoint?: CoordinationWaitPoint; private initializeState: LiveDataObjectInitializeState = LiveDataObjectInitializeState.needed; @@ -203,13 +241,29 @@ export class LiveMediaSessionCoordinator extends EventEmitter { } /** - * Max amount of playback drift allowed in seconds. + * Controls whether or not to scale {@link maxPlaybackDrift} by the number of users in the session. * * @remarks - * Should the local clients playback position lag by more than the specified value, the - * coordinator will trigger a `catchup` action. + * As more clients join a session, it is more likely that some users will fall behind the presenter. + * It is also less likely that users will notice drift as more clients are added. + * It is usually helpful to be more lenient as more clients are added so everyone can watch all the content. + * Default value is true. + */ + public get shouldScaleMaxPlaybackDrift(): boolean { + return this._maxPlaybackDrift.shouldPrioritize; + } + + public set shouldScaleMaxPlaybackDrift(value: boolean) { + this._maxPlaybackDrift.shouldPrioritize = value; + } + + /** + * Max amount of playback drift allowed in seconds. + * This will scale automatically according to the number of participants in the session when {@link shouldScaleMaxPlaybackDrift} is true. * - * Defaults to a value of `1` second. + * @remarks + * Should the local clients playback position lag by more than the specified value, the coordinator will trigger a `catchup` action. + * Default value is `1.5` seconds. */ public get maxPlaybackDrift(): number { return this._maxPlaybackDrift.seconds; @@ -220,11 +274,30 @@ export class LiveMediaSessionCoordinator extends EventEmitter { } /** - * Frequency with which position updates are broadcast to the rest of the group in - * seconds. + * Controls whether or not to compute {@link positionUpdateInterval} based on whether user has initiated a playback command. + * Default value is true. * * @remarks - * Defaults to a value of `2` seconds. + * When true, users that are simply watching but not controlling playback will report their positions less frequently. + * When a user has sent a transport command, they will begin sending position updates more frequently. + * Most Live Share apps have a concept of a primary presenter, and don't allow anyone to pause/play for the group. + * By ensuring only one/few users broadcast updates frequently, the server load is reduced considerably. + */ + public get shouldScalePositionUpdateInterval(): boolean { + return this._positionUpdateInterval.shouldPrioritize; + } + + public set shouldScalePositionUpdateInterval(value: boolean) { + this._positionUpdateInterval.shouldPrioritize = value; + } + + /** + * Frequency with which position updates are broadcast to the rest of the group in seconds. + * When {@link shouldScalePositionUpdateInterval} is set to `true`, the value set is the minimum value. + * The value returned is the actual value used to send updates by the local user, which may be larger than the value set. + * + * @remarks + * Defaults to a minimum value of `2` seconds. */ public get positionUpdateInterval(): number { return this._positionUpdateInterval.seconds; @@ -274,6 +347,10 @@ export class LiveMediaSessionCoordinator extends EventEmitter { track: this._groupState.playbackTrack.current, position: position, }); + if (this.canSendPositionUpdates) { + // User has taken initiative to send event, give priority for sending position updates + this._positionUpdateInterval.hasPriority = true; + } } /** @@ -316,6 +393,10 @@ export class LiveMediaSessionCoordinator extends EventEmitter { track: this._groupState.playbackTrack.current, position: position, }); + if (this.canSendPositionUpdates) { + // User has taken initiative to send event, give priority for sending position updates + this._positionUpdateInterval.hasPriority = true; + } } /** @@ -356,12 +437,24 @@ export class LiveMediaSessionCoordinator extends EventEmitter { track: this._groupState.playbackTrack.current, position: time, }); + if (this.canSendPositionUpdates) { + // User has taken initiative to send event, give priority for sending position updates + this._positionUpdateInterval.hasPriority = true; + } } catch (err) { await this._groupState!.syncLocalMediaSession(); throw err; } } + /** + * Sets the playback rate for everyone in the session. + * + * @param playbackRate the playback rate to set. + * + * @throws + * Throws an exception if the session/coordinator hasn't been initialized or {@link canSetPlaybackRate} is false. + */ public async setPlaybackRate(playbackRate: number): Promise { LiveDataObjectNotInitializedError.assert( "LiveMediaSessionCoordinator:setPlaybackRate", @@ -381,6 +474,10 @@ export class LiveMediaSessionCoordinator extends EventEmitter { { playbackRate } ); await this._rateChangeEvent!.sendEvent({ playbackRate }); + if (this.canSendPositionUpdates) { + // User has taken initiative to send event, give priority for sending position updates + this._positionUpdateInterval.hasPriority = true; + } } /** @@ -417,6 +514,10 @@ export class LiveMediaSessionCoordinator extends EventEmitter { metadata: metadata, waitPoints: waitPoints || [], }); + if (this.canSendPositionUpdates) { + // User has taken initiative to send event, give priority for sending position updates + this._positionUpdateInterval.hasPriority = true; + } } /** @@ -451,6 +552,10 @@ export class LiveMediaSessionCoordinator extends EventEmitter { await this._setTrackDataEvent!.sendEvent({ data: data, }); + if (this.canSendPositionUpdates) { + // User has taken initiative to send event, give priority for sending position updates + this._positionUpdateInterval.hasPriority = true; + } } /** @@ -570,13 +675,12 @@ export class LiveMediaSessionCoordinator extends EventEmitter { try { // start needs to happen after setting initializedState to "succeeded" - await this._synchronizer?.start( - undefined, - async (evt, sender, local) => false, - async (connecting) => true, - false, - false - ); + await this._synchronizer?.start({ + initialState: undefined, + updateState: async (evt, sender, local) => false, + getLocalUserCanSend: async (connecting) => true, + enableBackgroundUpdates: false, + }); } catch (error: unknown) { // not a fatal error for LiveMediaSession, only used for "connect" event to send new clients position updates. this._logger.sendErrorEvent( @@ -603,7 +707,10 @@ export class LiveMediaSessionCoordinator extends EventEmitter { * @hidden * Called by MediaSession to trigger the sending of a position update. */ - public sendPositionUpdate(state: IMediaPlayerState): void { + public sendPositionUpdate( + state: IMediaPlayerState, + targetClientId?: string + ): void { LiveDataObjectNotInitializedError.assert( "LiveMediaSessionCoordinator:sendPositionUpdate", "sendPositionUpdate", @@ -613,12 +720,15 @@ export class LiveMediaSessionCoordinator extends EventEmitter { if (this.canSendPositionUpdates) { // Send position update event const evt = this._groupState!.createPositionUpdateEvent(state); - this._positionUpdateEvent?.sendEvent(evt).catch((err) => { - this._logger.sendErrorEvent( - TelemetryEvents.SessionCoordinator.PositionUpdateEventError, - err - ); - }); + this._positionUpdateEvent + ?.sendEvent(evt, targetClientId) + .catch((err) => { + this._logger.sendErrorEvent( + TelemetryEvents.SessionCoordinator + .PositionUpdateEventError, + err + ); + }); } else if (this.isSuspended) { // send a local only position update event that was not sent as a signal, and use to handle local // position update for clients that have canSendPositionUpdates==false, but are suspending @@ -730,7 +840,9 @@ export class LiveMediaSessionCoordinator extends EventEmitter { // Immediately send a position update try { const state = this._getPlayerState(); - this.sendPositionUpdate(state); + // Send only to the user that joined the session using the targetClientId prop. + // This ensures that only the user that connected receives this one-time position update, minimizing costs. + this.sendPositionUpdate(state, clientId); } catch (err: any) { // if player is not setup yet, local client might have also just joined and can't send its position. const playerNotSetup = diff --git a/packages/live-share-media/src/LiveMediaSessionCoordinatorSuspension.ts b/packages/live-share-media/src/LiveMediaSessionCoordinatorSuspension.ts index a85b35ba9..c8044ea3d 100644 --- a/packages/live-share-media/src/LiveMediaSessionCoordinatorSuspension.ts +++ b/packages/live-share-media/src/LiveMediaSessionCoordinatorSuspension.ts @@ -6,11 +6,9 @@ import { MediaSessionCoordinatorSuspension, CoordinationWaitPoint, -} from "./MediaSessionExtensions"; +} from "./MediaSessionExtensions.js"; -export class LiveMediaSessionCoordinatorSuspension - implements MediaSessionCoordinatorSuspension -{ +export class LiveMediaSessionCoordinatorSuspension implements MediaSessionCoordinatorSuspension { private _waitPoint?: CoordinationWaitPoint; private _onEnd: (seekTo?: number) => void; diff --git a/packages/live-share-media/src/MediaPlayerSynchronizer.ts b/packages/live-share-media/src/MediaPlayerSynchronizer.ts index 4c042c398..cf1398b2b 100644 --- a/packages/live-share-media/src/MediaPlayerSynchronizer.ts +++ b/packages/live-share-media/src/MediaPlayerSynchronizer.ts @@ -2,12 +2,11 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the Microsoft Live Share SDK License. */ +import { LiveTelemetryLogger, ILiveEvent } from "@microsoft/live-share"; import { - LiveTelemetryLogger, - ILiveEvent, IRuntimeSignaler, -} from "@microsoft/live-share"; -import EventEmitter from "events"; + waitUntilConnected, +} from "@microsoft/live-share/internal"; import { ExtendedMediaSessionAction, ExtendedMediaSessionPlaybackState, @@ -16,12 +15,14 @@ import { ExtendedMediaSessionActionDetails, MediaSessionCoordinatorEvents, MediaSessionCoordinatorSuspension, -} from "./MediaSessionExtensions"; -import { VolumeManager } from "./VolumeManager"; -import { LiveMediaSession } from "./LiveMediaSession"; -import { IMediaPlayer } from "./IMediaPlayer"; -import { ITriggerActionEvent, TelemetryEvents } from "./internals"; -import { waitUntilConnected } from "@microsoft/live-share/bin/internals"; +} from "./MediaSessionExtensions.js"; +import { VolumeManager } from "./VolumeManager.js"; +import { LiveMediaSession } from "./LiveMediaSession.js"; +import { IMediaPlayer } from "./IMediaPlayer.js"; +import { TelemetryEvents } from "./internals/consts.js"; +import { ITriggerActionEvent } from "./internals/GroupCoordinatorState.js"; +import { TypedEventEmitter } from "@fluid-internal/client-utils"; +import { IEvent } from "@fluidframework/core-interfaces"; /** * Event data returned by `MediaPlayerSynchronizer` object. @@ -49,6 +50,20 @@ export enum MediaPlayerSynchronizerEvents { useraction = "useraction", } +/** + * @hidden + * Emitted events from the `MediaPlayerSynchronizer` class. + */ +export interface IMediaPlayerSynchronizerEvents extends IEvent { + /** + * Event listener for events emitted + * @param event update + * @param listener listener function + * @param listener.event the event instance + */ + (event: string, listener: (event: any) => void): void; +} + /** * Synchronizes a local HTML Media Element with a group of remote HTML Media Elements. * @@ -58,7 +73,7 @@ export enum MediaPlayerSynchronizerEvents { * to the local player. When the group session is joined the commands will be broadcast to the * group in addition to being applied to the local player. */ -export class MediaPlayerSynchronizer extends EventEmitter { +export class MediaPlayerSynchronizer extends TypedEventEmitter { private static SESSION_ACTIONS: ExtendedMediaSessionAction[] = [ "play", "pause", diff --git a/packages/live-share-media/src/MediaSessionActionThrottler.ts b/packages/live-share-media/src/MediaSessionActionThrottler.ts index 2b4de68db..859c2dcd1 100644 --- a/packages/live-share-media/src/MediaSessionActionThrottler.ts +++ b/packages/live-share-media/src/MediaSessionActionThrottler.ts @@ -6,7 +6,7 @@ import { ExtendedMediaSessionActionDetails, ExtendedMediaSessionActionHandler, -} from "./MediaSessionExtensions"; +} from "./MediaSessionExtensions.js"; /** * Base class for action throttlers. diff --git a/packages/live-share-media/src/RepeatedActionThrottler.ts b/packages/live-share-media/src/RepeatedActionThrottler.ts index 44502374f..6cd90ae07 100644 --- a/packages/live-share-media/src/RepeatedActionThrottler.ts +++ b/packages/live-share-media/src/RepeatedActionThrottler.ts @@ -4,11 +4,11 @@ */ import { TimeInterval } from "@microsoft/live-share"; -import { MediaSessionActionThrottler } from "./MediaSessionActionThrottler"; +import { MediaSessionActionThrottler } from "./MediaSessionActionThrottler.js"; import { ExtendedMediaSessionActionDetails, ExtendedMediaSessionAction, -} from "./MediaSessionExtensions"; +} from "./MediaSessionExtensions.js"; /** * A Throttler that passes through all actions but will only let an action be repeated once every 2 seconds. diff --git a/packages/live-share-media/src/VolumeManager.ts b/packages/live-share-media/src/VolumeManager.ts index 51fec4bff..be592cf30 100644 --- a/packages/live-share-media/src/VolumeManager.ts +++ b/packages/live-share-media/src/VolumeManager.ts @@ -4,7 +4,7 @@ */ import { TimeInterval } from "@microsoft/live-share"; -import { IMediaPlayer } from "./IMediaPlayer"; +import { IMediaPlayer } from "./IMediaPlayer.js"; export enum LimitLevelType { fixed, @@ -61,12 +61,12 @@ export class VolumeManager { * * @remarks * Expressed as a value between 0.0 and 1.0. The value is applied based upon the configured - * `levelType`. The default value is 0.1. + * @see LimitLevelType. The default value is 0.1. * - * For a level type of `LevelType.fixed` the value is the exact level the volume will be + * For a level type of @see LimitLevelType.fixed the value is the exact level the volume will be * lowered to. The default value of 0.1 would cause the volume to be lowered to 0.1. * - * For a level type of `LevelType.percentage` the value is the percentage by which the volume + * For a level type of @see LimitLevelType.percentage the value is the percentage by which the volume * level should be lowered to. The default value of 0.1 would cause the volume to be lowered * to 10% of its starting value. */ @@ -118,8 +118,8 @@ export class VolumeManager { /** * Limits volume based on `limitLevel` and `limitLevelType` properties. - * @see `limitLevel` - * @see `limitLevelType` + * @see limitLevel + * @see limitLevelType */ public startLimiting(): void { this._isLimiting = true; diff --git a/packages/live-share-media/src/index.ts b/packages/live-share-media/src/index.ts index c9e774faf..9fcc2c223 100644 --- a/packages/live-share-media/src/index.ts +++ b/packages/live-share-media/src/index.ts @@ -3,12 +3,12 @@ * Licensed under the Microsoft Live Share SDK License. */ -export * from "./LiveMediaSession"; -export * from "./LiveMediaSessionCoordinator"; -export * from "./LiveMediaSessionCoordinatorSuspension"; -export * from "./IMediaPlayer"; -export * from "./MediaPlayerSynchronizer"; -export * from "./MediaSessionActionThrottler"; -export * from "./MediaSessionExtensions"; -export * from "./RepeatedActionThrottler"; -export * from "./VolumeManager"; +export * from "./LiveMediaSession.js"; +export * from "./LiveMediaSessionCoordinator.js"; +export * from "./LiveMediaSessionCoordinatorSuspension.js"; +export * from "./IMediaPlayer.js"; +export * from "./MediaPlayerSynchronizer.js"; +export * from "./MediaSessionActionThrottler.js"; +export * from "./MediaSessionExtensions.js"; +export * from "./RepeatedActionThrottler.js"; +export * from "./VolumeManager.js"; diff --git a/packages/live-share-media/src/internals/GroupCoordinatorState.ts b/packages/live-share-media/src/internals/GroupCoordinatorState.ts index bfa803460..258ce121c 100644 --- a/packages/live-share-media/src/internals/GroupCoordinatorState.ts +++ b/packages/live-share-media/src/internals/GroupCoordinatorState.ts @@ -6,50 +6,54 @@ import { ILiveEvent, TimeInterval, - IRuntimeSignaler, LiveTelemetryLogger, - LiveShareRuntime, IEvent, } from "@microsoft/live-share"; -import EventEmitter from "events"; +import { + IRuntimeSignaler, + LiveShareRuntime, + waitUntilConnected, +} from "@microsoft/live-share/internal"; import { ExtendedMediaMetadata, CoordinationWaitPoint, ExtendedMediaSessionPlaybackState, ExtendedMediaSessionActionDetails, ExtendedMediaSessionActionSource, -} from "../MediaSessionExtensions"; +} from "../MediaSessionExtensions.js"; import { GroupPlaybackTrack, GroupPlaybackTrackEvents, IPlaybackTrack, IPlaybackTrackChangeEvent, -} from "./GroupPlaybackTrack"; +} from "./GroupPlaybackTrack.js"; import { GroupTransportState, ITransportState, ITransportStateChangeEvent, -} from "./GroupTransportState"; +} from "./GroupTransportState.js"; import { GroupPlaybackPosition, ICurrentPlaybackPosition, -} from "./GroupPlaybackPosition"; -import { IMediaPlayerState } from "../LiveMediaSessionCoordinator"; -import { GroupTransportStateEvents } from "./GroupTransportState"; +} from "./GroupPlaybackPosition.js"; +import { IMediaPlayerState } from "../LiveMediaSessionCoordinator.js"; +import { GroupTransportStateEvents } from "./GroupTransportState.js"; import { GroupPlaybackTrackData, PlaybackTrackDataEvents, IPlaybackTrackData, IPlaybackTrackDataChangeEvent, -} from "./GroupPlaybackTrackData"; -import { TelemetryEvents } from "./consts"; -import { waitUntilConnected } from "@microsoft/live-share/bin/internals"; +} from "./GroupPlaybackTrackData.js"; +import { TelemetryEvents } from "./consts.js"; import { GroupPlaybackRate, IPlaybackRate, IPlaybackRateChangeEvent, PlaybackRateEvents, -} from "./GroupPlaybackRate"; +} from "./GroupPlaybackRate.js"; +import { TypedEventEmitter } from "@fluid-internal/client-utils"; +import { IGenericTypedEvents } from "./interfaces.js"; +import { PriorityTimeInterval } from "./PriorityTimeInterval.js"; /** * @hidden @@ -113,7 +117,7 @@ export enum GroupCoordinatorStateEvents { /** * @hidden */ -export class GroupCoordinatorState extends EventEmitter { +export class GroupCoordinatorState extends TypedEventEmitter { private readonly _runtime: IRuntimeSignaler; private readonly _liveRuntime: LiveShareRuntime; private readonly _logger: LiveTelemetryLogger; @@ -142,7 +146,7 @@ export class GroupCoordinatorState extends EventEmitter { runtime: IRuntimeSignaler, liveRuntime: LiveShareRuntime, maxPlaybackDrift: TimeInterval, - positionUpdateInterval: TimeInterval, + positionUpdateInterval: PriorityTimeInterval, getMediaPlayerState: () => IMediaPlayerState ) { super(); diff --git a/packages/live-share-media/src/internals/GroupPlaybackPosition.ts b/packages/live-share-media/src/internals/GroupPlaybackPosition.ts index c2d2fedd9..de8e10b70 100644 --- a/packages/live-share-media/src/internals/GroupPlaybackPosition.ts +++ b/packages/live-share-media/src/internals/GroupPlaybackPosition.ts @@ -5,16 +5,16 @@ import { IRuntimeSignaler, - TimeInterval, LiveShareRuntime, -} from "@microsoft/live-share"; -import { GroupTransportState } from "./GroupTransportState"; -import { GroupPlaybackTrackEvents } from "./GroupPlaybackTrack"; +} from "@microsoft/live-share/internal"; +import { GroupTransportState } from "./GroupTransportState.js"; +import { GroupPlaybackTrackEvents } from "./GroupPlaybackTrack.js"; import { CoordinationWaitPoint, ExtendedMediaSessionPlaybackState, -} from "../MediaSessionExtensions"; -import { GroupPlaybackRate } from "./GroupPlaybackRate"; +} from "../MediaSessionExtensions.js"; +import { GroupPlaybackRate } from "./GroupPlaybackRate.js"; +import { PriorityTimeInterval } from "./PriorityTimeInterval.js"; /** * Per client position @@ -37,7 +37,7 @@ export class GroupPlaybackPosition { private _playbackRate: GroupPlaybackRate; private _runtime: IRuntimeSignaler; private _liveRuntime: LiveShareRuntime; - private _updateInterval: TimeInterval; + private _updateInterval: PriorityTimeInterval; private _positions: Map; constructor( @@ -45,7 +45,7 @@ export class GroupPlaybackPosition { playbackRate: GroupPlaybackRate, runtime: IRuntimeSignaler, liveRuntime: LiveShareRuntime, - updateInterval: TimeInterval + updateInterval: PriorityTimeInterval ) { this._transportState = transportState; this._playbackRate = playbackRate; @@ -171,7 +171,7 @@ export class GroupPlaybackPosition { ) => void ): void { const now = this._liveRuntime.getTimestamp(); - const ignoreBefore = now - this._updateInterval.milliseconds * 2; + const ignoreBefore = now - this._updateInterval.maxMilliseconds * 2; const shouldProject = !this._transportState.track.metadata?.liveStream; this._positions.forEach((position, _) => { // Ignore any old updates diff --git a/packages/live-share-media/src/internals/GroupPlaybackRate.ts b/packages/live-share-media/src/internals/GroupPlaybackRate.ts index fd9781168..ad71a3d74 100644 --- a/packages/live-share-media/src/internals/GroupPlaybackRate.ts +++ b/packages/live-share-media/src/internals/GroupPlaybackRate.ts @@ -3,9 +3,9 @@ * Licensed under the Microsoft Live Share SDK License. */ -import EventEmitter from "events"; -import { ExtendedMediaSessionActionSource } from "../MediaSessionExtensions"; -import { IGroupStateEvent } from "./interfaces"; +import { TypedEventEmitter } from "@fluid-internal/client-utils"; +import { ExtendedMediaSessionActionSource } from "../MediaSessionExtensions.js"; +import { IGroupStateEvent, IGenericTypedEvents } from "./interfaces.js"; /** * @hidden @@ -33,7 +33,7 @@ export interface IPlaybackRateChangeEvent extends IGroupStateEvent { /** * @hidden */ -export class GroupPlaybackRate extends EventEmitter { +export class GroupPlaybackRate extends TypedEventEmitter { private _current: IPlaybackRate; constructor() { diff --git a/packages/live-share-media/src/internals/GroupPlaybackTrack.ts b/packages/live-share-media/src/internals/GroupPlaybackTrack.ts index 7e4f41ddd..587346b54 100644 --- a/packages/live-share-media/src/internals/GroupPlaybackTrack.ts +++ b/packages/live-share-media/src/internals/GroupPlaybackTrack.ts @@ -3,14 +3,14 @@ * Licensed under the Microsoft Live Share SDK License. */ -import EventEmitter from "events"; -import { IMediaPlayerState } from "../LiveMediaSessionCoordinator"; +import { IMediaPlayerState } from "../LiveMediaSessionCoordinator.js"; import { CoordinationWaitPoint, ExtendedMediaMetadata, ExtendedMediaSessionActionSource, -} from "../MediaSessionExtensions"; -import { IGroupStateEvent } from "./interfaces"; +} from "../MediaSessionExtensions.js"; +import { IGenericTypedEvents, IGroupStateEvent } from "./interfaces.js"; +import { TypedEventEmitter } from "@fluid-internal/client-utils"; /** * @hidden @@ -39,7 +39,7 @@ export interface IPlaybackTrackChangeEvent extends IGroupStateEvent { /** * @hidden */ -export class GroupPlaybackTrack extends EventEmitter { +export class GroupPlaybackTrack extends TypedEventEmitter { private readonly _getMediaPlayerState: () => IMediaPlayerState; private _current: IPlaybackTrack; diff --git a/packages/live-share-media/src/internals/GroupPlaybackTrackData.ts b/packages/live-share-media/src/internals/GroupPlaybackTrackData.ts index 6098b6c0b..b1f247e63 100644 --- a/packages/live-share-media/src/internals/GroupPlaybackTrackData.ts +++ b/packages/live-share-media/src/internals/GroupPlaybackTrackData.ts @@ -3,13 +3,13 @@ * Licensed under the Microsoft Live Share SDK License. */ -import EventEmitter from "events"; import { GroupPlaybackTrack, GroupPlaybackTrackEvents, -} from "./GroupPlaybackTrack"; -import { ExtendedMediaSessionActionSource } from "../MediaSessionExtensions"; -import { IGroupStateEvent } from "./interfaces"; +} from "./GroupPlaybackTrack.js"; +import { ExtendedMediaSessionActionSource } from "../MediaSessionExtensions.js"; +import { IGenericTypedEvents, IGroupStateEvent } from "./interfaces.js"; +import { TypedEventEmitter } from "@fluid-internal/client-utils"; /** * @hidden @@ -37,7 +37,7 @@ export interface IPlaybackTrackDataChangeEvent extends IGroupStateEvent { /** * @hidden */ -export class GroupPlaybackTrackData extends EventEmitter { +export class GroupPlaybackTrackData extends TypedEventEmitter { private _track: GroupPlaybackTrack; private _current: IPlaybackTrackData; diff --git a/packages/live-share-media/src/internals/GroupTransportState.ts b/packages/live-share-media/src/internals/GroupTransportState.ts index 0a35f46dd..99e0d728f 100644 --- a/packages/live-share-media/src/internals/GroupTransportState.ts +++ b/packages/live-share-media/src/internals/GroupTransportState.ts @@ -3,20 +3,20 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { LiveShareRuntime } from "@microsoft/live-share"; -import EventEmitter from "events"; -import { IMediaPlayerState } from "../LiveMediaSessionCoordinator"; +import { LiveShareRuntime } from "@microsoft/live-share/internal"; +import { TypedEventEmitter } from "@fluid-internal/client-utils"; +import { IMediaPlayerState } from "../LiveMediaSessionCoordinator.js"; import { ExtendedMediaSessionPlaybackState, ExtendedMediaSessionAction, ExtendedMediaSessionActionSource, -} from "../MediaSessionExtensions"; +} from "../MediaSessionExtensions.js"; import { GroupPlaybackTrack, GroupPlaybackTrackEvents, -} from "./GroupPlaybackTrack"; -import { IGroupStateEvent } from "./interfaces"; -import { GroupPlaybackRate } from "./GroupPlaybackRate"; +} from "./GroupPlaybackTrack.js"; +import { IGenericTypedEvents, IGroupStateEvent } from "./interfaces.js"; +import { GroupPlaybackRate } from "./GroupPlaybackRate.js"; /** * @hidden @@ -46,7 +46,7 @@ export interface ITransportStateChangeEvent extends IGroupStateEvent { /** * @hidden */ -export class GroupTransportState extends EventEmitter { +export class GroupTransportState extends TypedEventEmitter { private readonly _getMediaPlayerState: () => IMediaPlayerState; private _track: GroupPlaybackTrack; private _playbackRate: GroupPlaybackRate; diff --git a/packages/live-share-media/src/internals/PriorityTimeInterval.ts b/packages/live-share-media/src/internals/PriorityTimeInterval.ts new file mode 100644 index 000000000..49b48d7e3 --- /dev/null +++ b/packages/live-share-media/src/internals/PriorityTimeInterval.ts @@ -0,0 +1,76 @@ +import { TimeInterval } from "@microsoft/live-share"; + +function getScaledPriorityTimeMs( + minMilliseconds: number, + hasPriority: boolean, + shouldPrioritize: boolean, + scaleBy: number +): number { + if (!shouldPrioritize) return minMilliseconds; + if (hasPriority) return minMilliseconds; + return minMilliseconds * scaleBy; +} + +/** + * @hidden + * Time interval that can scale based on a scaling function. + */ +export class PriorityTimeInterval extends TimeInterval { + /** + * If true, local user has priority and will have the lowest possible millesecond value. + */ + public hasPriority: boolean; + /** + * If true, milliseconds will be scaled when {@link hasPriority} is false. + */ + public shouldPrioritize: boolean; + /** + * Function to get the scale ratio. + */ + private getScaleBy: () => number; + /** + * Time interval that can scale based on a scaling function. + * + * @param defaultMilliseconds the default minimum milliseconds + * @param getScaleByFn a function to scale the milliseconds by when {@link hasPriority} is false and {@link shouldPrioritize} is true. + * @param defaultHasPriority the default {@link hasPriority} value + * @param defaultShouldPrioritize the default {@link shouldPrioritize} value + */ + constructor( + defaultMilliseconds: number, + getScaleByFn: () => number, + defaultHasPriority: boolean = false, + defaultShouldPrioritize: boolean = true + ) { + super(defaultMilliseconds); + this.hasPriority = defaultHasPriority; + this.shouldPrioritize = defaultShouldPrioritize; + this.getScaleBy = getScaleByFn; + } + + public get milliseconds(): number { + return getScaledPriorityTimeMs( + this._milliseconds, + this.hasPriority, + this.shouldPrioritize, + this.getScaleBy() + ); + } + + public set milliseconds(value: number) { + this._milliseconds = value; + } + + public get minMilliseconds(): number { + return this._milliseconds; + } + + public get maxMilliseconds(): number { + return getScaledPriorityTimeMs( + this._milliseconds, + false, + this.shouldPrioritize, + this.getScaleBy() + ); + } +} diff --git a/packages/live-share-media/src/internals/index.ts b/packages/live-share-media/src/internals/index.ts deleted file mode 100644 index a7554e82e..000000000 --- a/packages/live-share-media/src/internals/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Microsoft Live Share SDK License. - */ - -export * from "./consts"; -export * from "./GroupCoordinatorState"; -export * from "./GroupPlaybackPosition"; -export * from "./GroupPlaybackTrack"; -export * from "./GroupPlaybackTrackData"; -export * from "./GroupTransportState"; -export * from "./GroupPlaybackRate"; -export * from "./errors"; diff --git a/packages/live-share-media/src/internals/interfaces.ts b/packages/live-share-media/src/internals/interfaces.ts index b140cd8f0..d559bf784 100644 --- a/packages/live-share-media/src/internals/interfaces.ts +++ b/packages/live-share-media/src/internals/interfaces.ts @@ -1,5 +1,6 @@ import { IEvent } from "@microsoft/live-share"; -import { ExtendedMediaSessionActionSource } from "../MediaSessionExtensions"; +import { IEvent as IFluidEvent } from "@fluidframework/core-interfaces"; +import { ExtendedMediaSessionActionSource } from "../MediaSessionExtensions.js"; /** * @hidden @@ -8,3 +9,16 @@ export interface IGroupStateEvent extends IEvent { clientId: string; source: ExtendedMediaSessionActionSource; } + +/** + * @hidden + */ +export interface IGenericTypedEvents extends IFluidEvent { + /** + * Event listener for events emitted + * @param event update + * @param listener listener function + * @param listener.event the event instance + */ + (event: string, listener: (event: any) => void): void; +} diff --git a/packages/live-share-media/src/test/GroupPlaybackPosition.spec.ts b/packages/live-share-media/src/test/GroupPlaybackPosition.spec.ts index 51a4bdb23..ed0dd21b7 100644 --- a/packages/live-share-media/src/test/GroupPlaybackPosition.spec.ts +++ b/packages/live-share-media/src/test/GroupPlaybackPosition.spec.ts @@ -9,22 +9,26 @@ import { CoordinationWaitPoint, ExtendedMediaMetadata, ExtendedMediaSessionPlaybackState, -} from "../MediaSessionExtensions"; +} from "../MediaSessionExtensions.js"; import { GroupPlaybackPosition, - GroupPlaybackRate, - GroupPlaybackTrack, - GroupTransportState, ICurrentPlaybackPosition, +} from "../internals/GroupPlaybackPosition.js"; +import { GroupPlaybackRate } from "../internals/GroupPlaybackRate.js"; +import { + GroupTransportState, ITransportState, -} from "../internals"; +} from "../internals/GroupTransportState.js"; +import { TestLiveShareHost } from "@microsoft/live-share"; import { IRuntimeSignaler, - TestLiveShareHost, - TimeInterval, -} from "@microsoft/live-share"; -import { MockLiveShareRuntime } from "@microsoft/live-share/src/test/MockLiveShareRuntime"; -import { IMediaPlayerState } from "../LiveMediaSessionCoordinator"; + LiveShareRuntime, + MockLiveShareRuntime, + MockTokenProvider, +} from "@microsoft/live-share/internal"; +import { IMediaPlayerState } from "../LiveMediaSessionCoordinator.js"; +import { GroupPlaybackTrack } from "../internals/GroupPlaybackTrack.js"; +import { PriorityTimeInterval } from "../internals/PriorityTimeInterval.js"; function createTransportUpdate( runtime: IRuntimeSignaler, @@ -79,7 +83,7 @@ class MockRuntimeSignaler { } async function getObjects(updateInterval: number = 10000) { - const host = TestLiveShareHost.create(); + const host = TestLiveShareHost.create(new MockTokenProvider()); let liveRuntime = new MockLiveShareRuntime(false, updateInterval, host); let runtime1 = new MockRuntimeSignaler("1") as IRuntimeSignaler; @@ -101,7 +105,7 @@ async function getObjects(updateInterval: number = 10000) { async function getPlayBackPosition( liveRuntime: MockLiveShareRuntime, runtime1: IRuntimeSignaler, - updateInterval = new TimeInterval(10) + updateInterval = new PriorityTimeInterval(10, () => 1) ) { const track1 = { trackIdentifier: "track1", @@ -122,13 +126,13 @@ async function getPlayBackPosition( playbackTrack, plybackRate, getMediaPlayerState, - liveRuntime + liveRuntime as unknown as LiveShareRuntime ); const playbackPosition = new GroupPlaybackPosition( transportState, plybackRate, runtime1, - liveRuntime, + liveRuntime as unknown as LiveShareRuntime, updateInterval ); @@ -286,7 +290,7 @@ describe("GroupPlaybackPosition", () => { }); it("should enumerate client positions", async () => { - const updateInterval = new TimeInterval(10); + const updateInterval = new PriorityTimeInterval(10, () => 1); const { liveRuntime, runtime1, runtime2, dispose } = await getObjects(); const { playbackPosition } = await getPlayBackPosition( liveRuntime, @@ -325,7 +329,7 @@ describe("GroupPlaybackPosition", () => { }); it("should ignore stale positions", async () => { - const updateInterval = new TimeInterval(10); + const updateInterval = new PriorityTimeInterval(10, () => 1); const { liveRuntime, runtime1, runtime2, dispose } = await getObjects(); const { playbackPosition } = await getPlayBackPosition( liveRuntime, @@ -368,7 +372,7 @@ describe("GroupPlaybackPosition", () => { const { playbackPosition } = await getPlayBackPosition( liveRuntime, runtime1, - new TimeInterval(1000) + new PriorityTimeInterval(1000, () => 1) ); try { @@ -403,7 +407,7 @@ describe("GroupPlaybackPosition", () => { const { playbackPosition, transportState } = await getPlayBackPosition( liveRuntime, runtime1, - new TimeInterval(1000) + new PriorityTimeInterval(1000, () => 1) ); try { @@ -434,7 +438,7 @@ describe("GroupPlaybackPosition", () => { const { playbackPosition, transportState } = await getPlayBackPosition( liveRuntime, runtime1, - new TimeInterval(1000) + new PriorityTimeInterval(1000, () => 1) ); try { @@ -476,7 +480,7 @@ describe("GroupPlaybackPosition", () => { const { playbackPosition, transportState } = await getPlayBackPosition( liveRuntime, runtime1, - new TimeInterval(1000) + new PriorityTimeInterval(1000, () => 1) ); try { @@ -529,7 +533,7 @@ describe("GroupPlaybackPosition", () => { const { playbackPosition, transportState } = await getPlayBackPosition( liveRuntime, runtime1, - new TimeInterval(1000) + new PriorityTimeInterval(1000, () => 1) ); try { @@ -572,7 +576,7 @@ describe("GroupPlaybackPosition", () => { const { playbackPosition, transportState } = await getPlayBackPosition( liveRuntime, runtime1, - new TimeInterval(1000) + new PriorityTimeInterval(1000, () => 1) ); try { @@ -608,7 +612,7 @@ describe("GroupPlaybackPosition", () => { const { playbackPosition, transportState } = await getPlayBackPosition( liveRuntime, runtime1, - new TimeInterval(1000) + new PriorityTimeInterval(1000, () => 1) ); try { diff --git a/packages/live-share-media/src/test/GroupPlaybackRate.spec.ts b/packages/live-share-media/src/test/GroupPlaybackRate.spec.ts index ecfce422a..5317d4ed0 100644 --- a/packages/live-share-media/src/test/GroupPlaybackRate.spec.ts +++ b/packages/live-share-media/src/test/GroupPlaybackRate.spec.ts @@ -5,7 +5,7 @@ import "mocha"; import { strict as assert } from "assert"; -import { GroupPlaybackRate } from "../internals"; +import { GroupPlaybackRate } from "../internals/GroupPlaybackRate.js"; describe("GroupPlaybackRate", () => { it("updatePlaybackRate should return false for older events", () => { diff --git a/packages/live-share-media/src/test/GroupPlaybackTrack.spec.ts b/packages/live-share-media/src/test/GroupPlaybackTrack.spec.ts index 9f1eb8b58..ee8aed0b2 100644 --- a/packages/live-share-media/src/test/GroupPlaybackTrack.spec.ts +++ b/packages/live-share-media/src/test/GroupPlaybackTrack.spec.ts @@ -9,9 +9,9 @@ import { GroupPlaybackTrack, GroupPlaybackTrackEvents, IPlaybackTrackChangeEvent, -} from "../internals/GroupPlaybackTrack"; -import { ExtendedMediaMetadata } from "../MediaSessionExtensions"; -import { Deferred } from "@microsoft/live-share/src/internals/Deferred"; +} from "../internals/GroupPlaybackTrack.js"; +import { ExtendedMediaMetadata } from "../MediaSessionExtensions.js"; +import { Deferred } from "@microsoft/live-share/internal"; describe("GroupPlaybackTrack", () => { const track1 = { diff --git a/packages/live-share-media/src/test/GroupPlaybackTrackData.spec.ts b/packages/live-share-media/src/test/GroupPlaybackTrackData.spec.ts index 54a71a68b..e1aed8775 100644 --- a/packages/live-share-media/src/test/GroupPlaybackTrackData.spec.ts +++ b/packages/live-share-media/src/test/GroupPlaybackTrackData.spec.ts @@ -5,9 +5,9 @@ import "mocha"; import { strict as assert } from "assert"; -import { GroupPlaybackTrack } from "../internals/GroupPlaybackTrack"; -import { ExtendedMediaMetadata } from "../MediaSessionExtensions"; -import { GroupPlaybackTrackData } from "../internals"; +import { GroupPlaybackTrack } from "../internals/GroupPlaybackTrack.js"; +import { ExtendedMediaMetadata } from "../MediaSessionExtensions.js"; +import { GroupPlaybackTrackData } from "../internals/GroupPlaybackTrackData.js"; describe("GroupPlaybackTrackData", () => { const track1 = { diff --git a/packages/live-share-media/src/test/LiveMediaSession_ManualActionHandler.spec.ts b/packages/live-share-media/src/test/LiveMediaSession_ManualActionHandler.spec.ts index 644df0529..8f1acce9e 100644 --- a/packages/live-share-media/src/test/LiveMediaSession_ManualActionHandler.spec.ts +++ b/packages/live-share-media/src/test/LiveMediaSession_ManualActionHandler.spec.ts @@ -3,35 +3,50 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { TestLiveMediaSession, TestMediaTimeStampProvider } from "./TestUtils"; -import { Deferred } from "@microsoft/live-share/src/internals/Deferred"; +import { + TestLiveMediaSession, + TestMediaTimeStampProvider, +} from "./TestUtils.js"; import { strict as assert } from "assert"; -import { requestFluidObject } from "@fluidframework/runtime-utils"; -import { ITestObjectProvider } from "@fluidframework/test-utils"; -import { describeNoCompat } from "@fluidframework/test-version-utils"; +import { + ITestObjectProvider, + fluidEntryPoint, + getContainerEntryPointBackCompat, +} from "@fluidframework/test-utils/internal"; import { ITimestampProvider, - LiveEventScope, - LiveEventTarget, LocalTimestampProvider, UserMeetingRole, + TestLiveShareHost, } from "@microsoft/live-share"; -import { TestLiveShareHost } from "@microsoft/live-share"; -import { getLiveDataObjectClass } from "@microsoft/live-share"; -import { waitForDelay } from "@microsoft/live-share/src/internals"; -import { MockLiveShareRuntime } from "@microsoft/live-share/src/test/MockLiveShareRuntime"; +import { + getLiveDataObjectKind, + LiveEventScope, + LiveEventTarget, + MockLiveShareRuntime, + MockTokenProvider, + waitForDelay, + Deferred, + LiveShareRuntime, +} from "@microsoft/live-share/internal"; import { ExtendedMediaMetadata, ExtendedMediaSessionActionDetails, -} from "../MediaSessionExtensions"; -import { IMediaPlayerState } from "../LiveMediaSessionCoordinator"; +} from "../MediaSessionExtensions.js"; +import { IMediaPlayerState } from "../LiveMediaSessionCoordinator.js"; +import { + ITestObjectProviderOptions, + describeCompat, +} from "@live-share-private/test-utils"; async function getObjects( - getTestObjectProvider, + getTestObjectProvider: ( + options?: ITestObjectProviderOptions + ) => ITestObjectProvider, updateInterval: number = 10000, timestampProvider: ITimestampProvider = new LocalTimestampProvider() ) { - const host = TestLiveShareHost.create(); + const host = TestLiveShareHost.create(new MockTokenProvider()); let liveRuntime1 = new MockLiveShareRuntime( false, updateInterval, @@ -45,13 +60,13 @@ async function getObjects( timestampProvider ); - let ObjectProxy1: any = getLiveDataObjectClass( + let ObjectProxy1: any = getLiveDataObjectKind( TestLiveMediaSession, - liveRuntime1 + liveRuntime1 as unknown as LiveShareRuntime ); - let ObjectProxy2: any = getLiveDataObjectClass( + let ObjectProxy2: any = getLiveDataObjectKind( TestLiveMediaSession, - liveRuntime2 + liveRuntime2 as unknown as LiveShareRuntime ); await liveRuntime1.start(); @@ -59,18 +74,21 @@ async function getObjects( let provider: ITestObjectProvider = getTestObjectProvider(); - let container1 = await provider.createContainer(ObjectProxy1.factory); - let object1 = await requestFluidObject( - container1, - "default" + let container1 = await provider.createContainer( + ObjectProxy1.factory as fluidEntryPoint ); + let object1 = + await getContainerEntryPointBackCompat( + container1 + ); object1.coordinator.positionUpdateInterval = 0.02; - - let container2 = await provider.loadContainer(ObjectProxy2.factory); - let object2 = await requestFluidObject( - container2, - "default" + let container2 = await provider.loadContainer( + ObjectProxy2.factory as fluidEntryPoint ); + let object2 = + await getContainerEntryPointBackCompat( + container2 + ); object2.coordinator.positionUpdateInterval = 0.02; const track1 = { @@ -119,7 +137,7 @@ async function getObjects( }; } -describeNoCompat( +describeCompat( "LiveMediaSession Manual Action Handlers (mostly testing coordinator)", (getTestObjectProvider) => { it("should send 'positionUpdate' event when someone joins.", async () => { @@ -131,19 +149,17 @@ describeNoCompat( // wait for next event loop, simulate existing user waiting for other people to join. // otherwise joined event will fire for both users await waitForDelay(1); - - // create a duplicate scope/target with same event name as one declared in coordinator - const scope2 = new LiveEventScope( - object2.runtimeForTesting(), - object2.liveRuntimeForTesting() - ); let positionUpdateCount = 0; - new LiveEventTarget(scope2, "positionUpdate", (event, local) => { - // assert(!local, JSON.stringify(event)); - positionUpdateCount += 1; - }); await object2.initialize(); + // @ts-ignore-next-line + object2.coordinator._positionUpdateEvent!._scope.onEvent( + "positionUpdate", + (event, local) => { + // assert(!local, JSON.stringify(event)); + positionUpdateCount += 1; + } + ); // wait for next event loop await waitForDelay(1); @@ -228,9 +244,8 @@ describeNoCompat( await object1.coordinator.seekTo(30); object1.coordinator.sendPositionUpdate(positionState(30)); - object2.coordinator.beginSuspension(); - + await waitForDelay(1); object2.coordinator.sendPositionUpdate(positionState(200)); await waitForDelay(1); diff --git a/packages/live-share-media/src/test/LiveMediaSession_Synchronizer.spec.ts b/packages/live-share-media/src/test/LiveMediaSession_Synchronizer.spec.ts index 01213cdc9..6a3223089 100644 --- a/packages/live-share-media/src/test/LiveMediaSession_Synchronizer.spec.ts +++ b/packages/live-share-media/src/test/LiveMediaSession_Synchronizer.spec.ts @@ -7,41 +7,53 @@ import { TestLiveMediaSession, TestMediaPlayer, TestMediaTimeStampProvider, -} from "./TestUtils"; -import { Deferred } from "@microsoft/live-share/src/internals/Deferred"; +} from "./TestUtils.js"; import { strict as assert } from "assert"; -import { requestFluidObject } from "@fluidframework/runtime-utils"; -import { ITestObjectProvider } from "@fluidframework/test-utils"; -import { describeNoCompat } from "@fluidframework/test-version-utils"; +import { + getContainerEntryPointBackCompat, + fluidEntryPoint, + ITestObjectProvider, +} from "@fluidframework/test-utils/internal"; import { ITimestampProvider, LocalTimestampProvider, + TestLiveShareHost, UserMeetingRole, } from "@microsoft/live-share"; -import { TestLiveShareHost } from "@microsoft/live-share"; -import { getLiveDataObjectClass } from "@microsoft/live-share"; -import { waitForDelay } from "@microsoft/live-share/src/internals"; -import { MockLiveShareRuntime } from "@microsoft/live-share/src/test/MockLiveShareRuntime"; -import { isErrorLike } from "@microsoft/live-share/bin/internals"; +import { + Deferred, + getLiveDataObjectKind, + isErrorLike, + LiveShareRuntime, + MockLiveShareRuntime, + MockTokenProvider, + waitForDelay, +} from "@microsoft/live-share/internal"; import { ExtendedMediaMetadata, ExtendedMediaSessionAction, ExtendedMediaSessionActionDetails, ExtendedMediaSessionActionIgnore, ExtendedMediaSessionActionSource, -} from "../MediaSessionExtensions"; +} from "../MediaSessionExtensions.js"; import { IMediaPlayerSynchronizerEvent, MediaPlayerSynchronizer, MediaPlayerSynchronizerEvents, -} from "../MediaPlayerSynchronizer"; +} from "../MediaPlayerSynchronizer.js"; +import { + ITestObjectProviderOptions, + describeCompat, +} from "@live-share-private/test-utils"; async function getObjects( - getTestObjectProvider, + getTestObjectProvider: ( + options?: ITestObjectProviderOptions + ) => ITestObjectProvider, updateInterval: number = 10000, timestampProvider: ITimestampProvider = new LocalTimestampProvider() ) { - const host = TestLiveShareHost.create(); + const host = TestLiveShareHost.create(new MockTokenProvider()); let liveRuntime1 = new MockLiveShareRuntime( false, updateInterval, @@ -55,13 +67,13 @@ async function getObjects( timestampProvider ); - let ObjectProxy1: any = getLiveDataObjectClass( + let ObjectProxy1: any = getLiveDataObjectKind( TestLiveMediaSession, - liveRuntime1 + liveRuntime1 as unknown as LiveShareRuntime ); - let ObjectProxy2: any = getLiveDataObjectClass( + let ObjectProxy2: any = getLiveDataObjectKind( TestLiveMediaSession, - liveRuntime2 + liveRuntime2 as unknown as LiveShareRuntime ); await liveRuntime1.start(); @@ -69,18 +81,21 @@ async function getObjects( let provider: ITestObjectProvider = getTestObjectProvider(); - let container1 = await provider.createContainer(ObjectProxy1.factory); - let object1 = await requestFluidObject( - container1, - "default" + let container1 = await provider.createContainer( + ObjectProxy1.factory as fluidEntryPoint ); + let object1 = + await getContainerEntryPointBackCompat( + container1 + ); object1.coordinator.positionUpdateInterval = 0.02; - - let container2 = await provider.loadContainer(ObjectProxy2.factory); - let object2 = await requestFluidObject( - container2, - "default" + let container2 = await provider.loadContainer( + ObjectProxy2.factory as fluidEntryPoint ); + let object2 = + await getContainerEntryPointBackCompat( + container2 + ); object2.coordinator.positionUpdateInterval = 0.02; // need to be connected to send signals if (!container1.connect) { @@ -111,7 +126,7 @@ async function getObjects( }; } -describeNoCompat( +describeCompat( "LiveMediaSession Using MediaPlayerSynchronizer", (getTestObjectProvider) => { it("should play and pause on both", async () => { diff --git a/packages/live-share-media/src/test/PriorityTimeInterval.spec.ts b/packages/live-share-media/src/test/PriorityTimeInterval.spec.ts new file mode 100644 index 000000000..1f9faa098 --- /dev/null +++ b/packages/live-share-media/src/test/PriorityTimeInterval.spec.ts @@ -0,0 +1,77 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Microsoft Live Share SDK License. + */ + +import "mocha"; +import { strict as assert } from "assert"; +import { PriorityTimeInterval } from "../internals/PriorityTimeInterval.js"; + +describe("PriorityTimeInterval", () => { + it("Should scale properly with default values in constructor", () => { + const interval = new PriorityTimeInterval(1000, () => 2); + assert(interval.milliseconds === 2000); + assert(interval.seconds === 2); + }); + + it("Should not scale when starting with priority", () => { + const interval = new PriorityTimeInterval(1000, () => 2, true); + assert(interval.milliseconds === 1000); + assert(interval.seconds === 1); + }); + + it("Should not scale when user does not have priority but scaling is disabled", () => { + const interval = new PriorityTimeInterval(1000, () => 2, false, false); + assert(interval.milliseconds === 1000); + assert(interval.seconds === 1); + }); + + it("Should scale properly after changing values", () => { + const interval = new PriorityTimeInterval(1000, () => 2); + assert(interval.milliseconds === 2000); + assert(interval.seconds === 2); + // Changing settings will break ts checks, since we asserted above that milliseconds was 2000 and ts can't figure out relationship. + // We ignore ts for lines where this occurs. + interval.hasPriority = true; + + // @ts-ignore-next + assert(interval.milliseconds === 1000); + // @ts-ignore-next + assert(interval.seconds === 1); + + interval.hasPriority = false; + + // @ts-ignore-next + assert(interval.milliseconds === 2000); + // @ts-ignore-next + assert(interval.seconds === 2); + + interval.shouldPrioritize = false; + + // @ts-ignore-next + assert(interval.milliseconds === 1000); + // @ts-ignore-next + assert(interval.seconds === 1); + + interval.shouldPrioritize = true; + + // @ts-ignore-next + assert(interval.milliseconds === 2000); + // @ts-ignore-next + assert(interval.seconds === 2); + }); + + it("Should dynamically scale depending on scaleBy func response", () => { + let scaleBy = 2; + const interval = new PriorityTimeInterval(1000, () => scaleBy); + assert(interval.milliseconds === 2000); + assert(interval.seconds === 2); + // Changing scaleBy will break ts checks, since we asserted above that milliseconds was 2000 and ts can't figure out relationship. + // We ignore ts for lines where this occurs. + scaleBy = 3; + // @ts-ignore-next + assert(interval.milliseconds === 3000); + // @ts-ignore-next + assert(interval.seconds === 3); + }); +}); diff --git a/packages/live-share-media/src/test/TestUtils.ts b/packages/live-share-media/src/test/TestUtils.ts index 29ed7d7f2..e087d2614 100644 --- a/packages/live-share-media/src/test/TestUtils.ts +++ b/packages/live-share-media/src/test/TestUtils.ts @@ -3,14 +3,14 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { IMediaPlayer } from "../IMediaPlayer"; -import { Deferred } from "@microsoft/live-share/src/internals/Deferred"; -import { LiveMediaSession } from "../LiveMediaSession"; +import { IMediaPlayer } from "../IMediaPlayer.js"; +import { LiveMediaSession } from "../LiveMediaSession.js"; +import { ITimestampProvider } from "@microsoft/live-share"; import { + Deferred, IRuntimeSignaler, - ITimestampProvider, LiveShareRuntime, -} from "@microsoft/live-share"; +} from "@microsoft/live-share/internal"; export class TestMediaPlayer implements IMediaPlayer { private done = new Deferred(); @@ -18,15 +18,15 @@ export class TestMediaPlayer implements IMediaPlayer { private _currentTime: number = 0; private _playbackRate: number = 1; - duration: number; - ended: boolean; - muted: boolean; + duration: number = 0; + ended: boolean = false; + muted: boolean = false; paused: boolean = true; src: string = "test"; - currentSrc: string; - volume: number; + currentSrc: string = ""; + volume: number = 1; - constructor(public onCurrentTimeSet?: (number) => void) { + constructor(public onCurrentTimeSet?: (number: number) => void) { setInterval(() => { if (!this.paused && this.playStartTime != 0) { this._currentTime = diff --git a/packages/live-share-media/src/test/VolumeManager.spec.ts b/packages/live-share-media/src/test/VolumeManager.spec.ts index e52b9eaa0..3002f2359 100644 --- a/packages/live-share-media/src/test/VolumeManager.spec.ts +++ b/packages/live-share-media/src/test/VolumeManager.spec.ts @@ -1,7 +1,7 @@ import { strict as assert } from "assert"; -import { IMediaPlayer } from "../IMediaPlayer"; -import { LimitLevelType, VolumeManager } from "../VolumeManager"; -import { Deferred, waitForDelay } from "@microsoft/live-share/src/internals"; +import { IMediaPlayer } from "../IMediaPlayer.js"; +import { LimitLevelType, VolumeManager } from "../VolumeManager.js"; +import { Deferred, waitForDelay } from "@microsoft/live-share/internal"; // few millis more than max timeout callback in scheduleAnimationFrame const milliTolerance = 25; @@ -47,11 +47,14 @@ describe("VolumeManager", () => { assert(player.volume == volumeManager.limitLevel); volumeManager.stopLimiting(); - setTimeout(() => { - // check volume at halfway point - assert(player.volume > 0.4); - assert(player.volume < 0.6); - }, (volumeManager.volumeChangeDuration * 1000) / 2); + setTimeout( + () => { + // check volume at halfway point + assert(player.volume > 0.4); + assert(player.volume < 0.6); + }, + (volumeManager.volumeChangeDuration * 1000) / 2 + ); // check volume at end with milliTollerance of leeway await waitForDelay( @@ -89,11 +92,14 @@ describe("VolumeManager", () => { volumeManager.volumeChangeDuration = volumeChangeDuration; volumeManager.volume = 0.3; - setTimeout(() => { - // check volume at halfway point - assert(player.volume > 0.6); - assert(player.volume < 0.7); - }, (volumeManager.volumeChangeDuration * 1000) / 2); + setTimeout( + () => { + // check volume at halfway point + assert(player.volume > 0.6); + assert(player.volume < 0.7); + }, + (volumeManager.volumeChangeDuration * 1000) / 2 + ); await waitForDelay( volumeManager.volumeChangeDuration * 1000 + milliTolerance @@ -157,11 +163,14 @@ describe("VolumeManager", () => { volumeManager.startLimiting(); - setTimeout(() => { - // check volume at halfway point - assert(player.volume > 0.7); - assert(player.volume < 0.8); - }, (volumeManager.volumeChangeDuration * 1000) / 2); + setTimeout( + () => { + // check volume at halfway point + assert(player.volume > 0.7); + assert(player.volume < 0.8); + }, + (volumeManager.volumeChangeDuration * 1000) / 2 + ); // check volume at end with milliTolerance of leeway await waitForDelay( @@ -175,15 +184,15 @@ describe("VolumeManager", () => { // test implementation class TestMediaPlayer implements IMediaPlayer { - currentSrc: string; - currentTime: number; - duration: number; - ended: boolean; - muted: boolean; - paused: boolean; - playbackRate: number; - src: string; - volume: number; + currentSrc: string = ""; + currentTime: number = 0; + duration: number = 0; + ended: boolean = false; + muted: boolean = false; + paused: boolean = false; + playbackRate: number = 1.0; + src: string = ""; + volume: number = 1; load(): void { throw new Error("Method not implemented."); } diff --git a/packages/live-share-media/tsconfig.build.json b/packages/live-share-media/tsconfig.build.json deleted file mode 100644 index 9d8cab4a6..000000000 --- a/packages/live-share-media/tsconfig.build.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ - }, - "exclude": [ - "test/**/*.ts" - ] - } \ No newline at end of file diff --git a/packages/live-share-media/tsconfig.json b/packages/live-share-media/tsconfig.json index 9d500ddde..f1195380b 100644 --- a/packages/live-share-media/tsconfig.json +++ b/packages/live-share-media/tsconfig.json @@ -1,76 +1,66 @@ { - "compilerOptions": { - /* Visit https://aka.ms/tsconfig.json to read more about this file */ - - /* Basic Options */ - // "incremental": true, /* Enable incremental compilation */ - "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ - "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ - "lib": ["es2020","DOM"], /* Specify library files to be included in the compilation. */ - "allowJs": false, /* Allow javascript files to be compiled. */ - // "checkJs": true, /* Report errors in .js files. */ - // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ - "declaration": true, /* Generates corresponding '.d.ts' file. */ - "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ - "sourceMap": true, /* Generates corresponding '.map' file. */ - // "outFile": "./", /* Concatenate and emit output to single file. */ - "outDir": "./bin", /* Redirect output structure to the directory. */ - // "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ - // "composite": true, /* Enable project compilation */ - // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ - // "removeComments": true, /* Do not emit comments to output. */ - // "noEmit": true, /* Do not emit outputs. */ - // "importHelpers": true, /* Import emit helpers from 'tslib'. */ - // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ - // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ - - /* Strict Type-Checking Options */ - "strict": true, /* Enable all strict type-checking options. */ - // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* Enable strict null checks. */ - // "strictFunctionTypes": true, /* Enable strict checking of function types. */ - // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ - // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ - // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ - // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ - - /* Additional Checks */ - // "noUnusedLocals": true, /* Report errors on unused locals. */ - // "noUnusedParameters": true, /* Report errors on unused parameters. */ - // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ - // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - - /* Module Resolution Options */ - // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ - // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ - // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ - // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ - // "typeRoots": [], /* List of folders to include type definitions from. */ - // "types": [], /* Type declaration files to be included in compilation. */ - // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ - "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ - // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - - /* Source Map Options */ - // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ - // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ - - /* Experimental Options */ - // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ - // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ - - /* Advanced Options */ - "skipLibCheck": true, /* Skip type checking of declaration files. */ - "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ - }, - "exclude": ["build", "dist", "node_modules"], - "include": [ - "test/**/*.ts" - ], - "files": [ - "src/index.ts" - ] + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + /* Basic Options */ + // "incremental": true, /* Enable incremental compilation */ + "target": "ES2022" /* Specify ECMAScript target version. */, + "module": "Node16" /* Specify module code generation. */, + "lib": [ + "ES2022", + "DOM" + ] /* Specify library files to be included in the compilation. */, + "allowJs": false /* Allow javascript files to be compiled. */, + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + "declaration": true /* Generates corresponding '.d.ts' file. */, + "declarationMap": true /* Generates a sourcemap for each corresponding '.d.ts' file. */, + "sourceMap": true /* Generates corresponding '.map' file. */, + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "./bin/esm" /* Redirect output structure to the directory. */, + // "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + /* Strict Type-Checking Options */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + /* Module Resolution Options */ + // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + /* Advanced Options */ + "skipLibCheck": true /* Skip type checking of declaration files. */, + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + }, + "files": ["src/index.ts"] } diff --git a/packages/live-share-media/tsconfig.test.json b/packages/live-share-media/tsconfig.test.json new file mode 100644 index 000000000..398bdec25 --- /dev/null +++ b/packages/live-share-media/tsconfig.test.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./bin/test", + "types": ["mocha", "node"] + }, + "files": [], + "include": ["src/**/*"], + "exclude": [] +} diff --git a/packages/live-share-media/typedoc.json b/packages/live-share-media/typedoc.json deleted file mode 100644 index 10851b2ed..000000000 --- a/packages/live-share-media/typedoc.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "entryPoints": ["./src/index.ts"], - "excludeExternals": true, - "excludePrivate": true, - "excludeInternal": true, - "name": "_microsoft_live_share_media", - "validation": { - "invalidLink": true - } -} diff --git a/packages/live-share-react/.nycrc.json b/packages/live-share-react/.nycrc.json index 37eeeda7d..6c6a7fa41 100644 --- a/packages/live-share-react/.nycrc.json +++ b/packages/live-share-react/.nycrc.json @@ -1,10 +1,10 @@ { - "cache": false, - "extension": [".ts"], - "check-coverage": true, - "include": ["src/**"], - "statements": 90, - "branches": 90, - "functions": 95, - "lines": 90 -} \ No newline at end of file + "cache": false, + "extension": [".ts"], + "check-coverage": true, + "include": ["src/**"], + "statements": 90, + "branches": 90, + "functions": 95, + "lines": 90 +} diff --git a/packages/live-share-react/LICENSE b/packages/live-share-react/LICENSE index 12ea5b6e7..59479a141 100644 --- a/packages/live-share-react/LICENSE +++ b/packages/live-share-react/LICENSE @@ -1,87 +1,90 @@ -MICROSOFT SOFTWARE LICENSE TERMS +MICROSOFT SOFTWARE LICENSE TERMS -MICROSOFT LIVE SHARE SDK – PRE-RELEASE VERSION +MICROSOFT LIVE SHARE SDK ________________________________________ -These license terms are an agreement between you and Microsoft Corporation (or one of its affiliates). They apply to the software named above and any Microsoft services or software updates (except to the extent such services or updates are accompanied by new or additional terms, in which case those different terms apply prospectively and do not alter your or Microsoft’s rights relating to pre-updated software or services). IF YOU COMPLY WITH THESE LICENSE TERMS, YOU HAVE THE RIGHTS BELOW. BY USING THE SOFTWARE, YOU ACCEPT THESE TERMS. +Copyright (c) Microsoft Corporation +All rights reserved + +These license terms are an agreement between you and Microsoft Corporation (or one of its affiliates). They apply to the software named above and any Microsoft services or software updates (except to the extent such services or updates are accompanied by new or additional terms, in which case those different terms apply prospectively and do not alter your or Microsoft’s rights relating to pre-updated software or services). IF YOU COMPLY WITH THESE LICENSE TERMS, YOU HAVE THE RIGHTS BELOW. BY USING THE SOFTWARE, YOU ACCEPT THESE TERMS. 1. INSTALLATION AND USE RIGHTS. - a) General. You may install and use any number of copies of the software to develop and test your applications, solely for the purpose stated in 1(b) below and otherwise for your internal business purposes. - b) Purpose. The use of this license provided under these terms is specifically limited to developing applications that interact solely within the Microsoft Teams Ecosystem. You may distribute the software according to Section 3 of these terms. - c) Third Party Components. The software may include third party components with separate legal notices or governed by other agreements, as may be described in the ThirdPartyNotices file(s) accompanying the software. - d) Microsoft Terms of Use. Some features of the software provide access to, or rely on, online services. The use of those services (but not the software) is governed by separate terms. This includes the Microsoft APIs Terms of Use which can be found at https://docs.microsoft.com/en-us/legal/microsoft-apis/terms-of-use and the Supplemental Terms of Use for Microsoft Azure which can be found at https://azure.microsoft.com/en-us/support/legal/preview-supplemental-terms. Please read them. The services may not be available in all regions. - -2. PRE-RELEASE SOFTWARE. The software is a pre-release version, and comes with no warranties as provided under Section 13. It may not operate correctly. We may change or discontinue the software at any time without notice. We may also choose not to make this software generally commercially available. It may be different from the commercially released version. - -3. DISTRIBUTABLE CODE. The software contains code you are permitted to distribute (i.e. make available for third parties) in applications you develop, as described in this Section. - a) Distribution Rights. The code and test files are distributable if included with the software. - i. Third Party Distribution. You may permit distributors of your applications to copy and distribute any of this distributable code you elect to distribute with your applications. - b) Distribution Requirements. For any code you distribute, you must: - i. adhere to the Purpose stated in Section 1(b); and - ii. indemnify, defend, and hold harmless Microsoft from any claims, including attorneys’ fees, related to the distribution or use of your applications, except to the extent that any claim is based solely on the unmodified distributable code. - c) Distribution Restrictions. You may not: - i. use Microsoft’s trademarks or trade dress in your application in any way that suggests your application comes from or is endorsed by Microsoft; or - ii. modify or distribute the source code of any distributable code so that any part of it becomes subject to any license that requires that the distributable code, any other part of the software, or any of Microsoft’s other intellectual property be disclosed or distributed in source code form, or that others have the right to modify it. - -4. SCOPE OF LICENSE. The software is licensed, not sold. Microsoft reserves all other rights. Unless applicable law gives you more rights despite this limitation, you will not (and have no right to): - a) remove, minimize, block, or modify any notices of Microsoft or its suppliers in the software;software; - b) use the software in any way that is against the law or to create or propagate malware; or - c) share, publish, distribute, or lease the software (except for any distributable code, subject to the terms above), provide the software as a stand-alone offering for others to use, or transfer the software or this agreement to any third party. + a) General. You may install and use any number of copies of the software to develop and test your applications, solely for the purpose stated in 1(b) below and otherwise for your internal business purposes. + b) Purpose. The use of this license provided under these terms is specifically limited to developing applications that interact solely within the Microsoft Teams Ecosystem. You may distribute the software according to Section 3 of these terms. + c) Third Party Components. The software may include third party components with separate legal notices or governed by other agreements, as may be described in the ThirdPartyNotices file(s) accompanying the software. + d) Microsoft Terms of Use. Some features of the software provide access to, or rely on, online services. The use of those services (but not the software) is governed by separate terms. This includes the Microsoft APIs Terms of Use which can be found at https://docs.microsoft.com/legal/microsoft-apis/terms-of-use, the Microsoft Developer Agreement which can be found at https://learn.microsoft.com/legal/mdsa, and the Supplemental Terms of Use for Microsoft Azure which can be found at https://azure.microsoft.com/support/legal/preview-supplemental-terms. Please read them. The services may not be available in all regions. + +2. NO WARRANTIES. The software comes with no warranties as provided under Section 13. It may not operate correctly. We may change or discontinue the software at any time without notice. + +3. DISTRIBUTABLE CODE. The software contains code you are permitted to distribute (i.e. make available for third parties) in applications you develop, as described in this Section. + a) Distribution Rights. The code and test files are distributable if included with the software. + i. Third Party Distribution. You may permit distributors of your applications to copy and distribute any of this distributable code you elect to distribute with your applications. + b) Distribution Requirements. For any code you distribute, you must: + i. adhere to the Purpose stated in Section 1(b); and + ii. indemnify, defend, and hold harmless Microsoft from any claims, including attorneys’ fees, related to the distribution or use of your applications, except to the extent that any claim is based solely on the unmodified distributable code. + c) Distribution Restrictions. You may not: + i. use Microsoft’s trademarks or trade dress in your application in any way that suggests your application comes from or is endorsed by Microsoft; or + ii. modify or distribute the source code of any distributable code so that any part of it becomes subject to any license that requires that the distributable code, any other part of the software, or any of Microsoft’s other intellectual property be disclosed or distributed in source code form, or that others have the right to modify it. + +4. SCOPE OF LICENSE. The software is licensed, not sold. Microsoft reserves all other rights. Unless applicable law gives you more rights despite this limitation, you will not (and have no right to): + a) remove, minimize, block, or modify any notices of Microsoft or its suppliers in the software;software; + b) use the software in any way that is against the law or to create or propagate malware; or + c) share, publish, distribute, or lease the software (except for any distributable code, subject to the terms above), provide the software as a stand-alone offering for others to use, or transfer the software or this agreement to any third party. 5. Data Protection. There are also some features in the software that may enable you to collect data from users of your applications. If you use these features to enable data collection in your applications, you must comply with applicable law, including providing appropriate notices to and obtaining consent from users of your applications. You can learn more about data collection and use in the help documentation and the privacy statement at https://aka.ms/privacy. Your use of the software operates as your consent to these practices. -6. CODE OF CONDUCT. By agreeing to these license terms, you’re agreeing that, when using the software, you will follow these rules: - a) Don’t do anything illegal. - b) Don’t engage in any activity that exploits, harms, or threatens to harm children. - c) Don’t send spam. Spam is unwanted or unsolicited bulk email, postings, contact requests, SMS (text messages), or instant messages. - d) Don’t publicly display or use the software to share inappropriate content or material (involving, for example, nudity, bestiality, pornography, offensive language, graphic violence, or criminal activity). - e) Don’t engage in activity that is fraudulent, false or misleading (e.g., asking for money under false pretenses, impersonating someone else, manipulating the software to increase play count, or affect rankings, ratings, or comments). - f) Don’t circumvent any restrictions on access to or availability of the software. - g) Don’t engage in activity that is harmful to you, the software, or others (e.g., transmitting viruses, stalking, posting terrorist content, communicating hate speech, or advocating violence against others). - h) Don’t infringe upon the rights of others (e.g., unauthorized sharing of copyrighted music or other copyrighted material, resale or other distribution of Bing maps, or photographs). - i) Don’t engage in activity that violates the privacy of others. - j) Don’t help others break these rules. +6. CODE OF CONDUCT. By agreeing to these license terms, you’re agreeing that, when using the software, you will follow these rules: + a) Don’t do anything illegal. + b) Don’t engage in any activity that exploits, harms, or threatens to harm children. + c) Don’t send spam. Spam is unwanted or unsolicited bulk email, postings, contact requests, SMS (text messages), or instant messages. + d) Don’t publicly display or use the software to share inappropriate content or material (involving, for example, nudity, bestiality, pornography, offensive language, graphic violence, or criminal activity). + e) Don’t engage in activity that is fraudulent, false or misleading (e.g., asking for money under false pretenses, impersonating someone else, manipulating the software to increase play count, or affect rankings, ratings, or comments). + f) Don’t circumvent any restrictions on access to or availability of the software. + g) Don’t engage in activity that is harmful to you, the software, or others (e.g., transmitting viruses, stalking, posting terrorist content, communicating hate speech, or advocating violence against others). + h) Don’t infringe upon the rights of others (e.g., unauthorized sharing of copyrighted music or other copyrighted material, resale or other distribution of Bing maps, or photographs). + i) Don’t engage in activity that violates the privacy of others. + j) Don’t help others break these rules. -7. EXPORT RESTRICTIONS. You must comply with all domestic and international export laws and regulations that apply to the software, which include restrictions on destinations, end users, and end use. For further information on export restrictions, visit https://aka.ms/exporting. +7. EXPORT RESTRICTIONS. You must comply with all domestic and international export laws and regulations that apply to the software, which include restrictions on destinations, end users, and end use. For further information on export restrictions, visit https://aka.ms/exporting. -8. SUPPORT SERVICES. Microsoft is not obligated under this agreement to provide any support services for the software. Any support provided is “as is”, “with all faults”, and without warranty of any kind. +8. SUPPORT SERVICES. Microsoft is not obligated under this agreement to provide any support services for the software. Any support provided is “as is”, “with all faults”, and without warranty of any kind. 9. ENTIRE AGREEMENT. This agreement, terms referenced herein, and any other terms Microsoft may provide for supplements, updates, or third-party applications, is the entire agreement for the software. -10. APPLICABLE LAW AND PLACE TO RESOLVE DISPUTES. If you acquired the software in the United States or Canada, the laws of the state or province where you live (or, if a business, where your principal place of business is located) govern the interpretation of this agreement, claims for its breach, and all other claims (including consumer protection, unfair competition, and tort claims), regardless of conflict of laws principles, except that the FAA governs everything related to arbitration. If you acquired the software in any other country, its laws apply, except that the FAA governs everything related to arbitration. If U.S. federal jurisdiction exists, you and Microsoft consent to exclusive jurisdiction and venue in the federal court in King County, Washington for all disputes heard in court (excluding arbitration). If not, you and Microsoft consent to exclusive jurisdiction and venue in the Superior Court of King County, Washington for all disputes heard in court (excluding arbitration). +10. APPLICABLE LAW AND PLACE TO RESOLVE DISPUTES. If you acquired the software in the United States or Canada, the laws of the state or province where you live (or, if a business, where your principal place of business is located) govern the interpretation of this agreement, claims for its breach, and all other claims (including consumer protection, unfair competition, and tort claims), regardless of conflict of laws principles, except that the FAA governs everything related to arbitration. If you acquired the software in any other country, its laws apply, except that the FAA governs everything related to arbitration. If U.S. federal jurisdiction exists, you and Microsoft consent to exclusive jurisdiction and venue in the federal court in King County, Washington for all disputes heard in court (excluding arbitration). If not, you and Microsoft consent to exclusive jurisdiction and venue in the Superior Court of King County, Washington for all disputes heard in court (excluding arbitration). + +11. CONSUMER RIGHTS; REGIONAL VARIATIONS. This agreement describes certain legal rights. You may have other rights, including consumer rights, under the laws of your state or country. Separate and apart from your relationship with Microsoft, you may also have rights with respect to the party from which you acquired the software. This agreement does not change those other rights if the laws of your state or country do not permit it to do so. For example, if you acquired the software in one of the below regions, or mandatory country law applies, then the following provisions apply to you: + a. Australia. You have statutory guarantees under the Australian Consumer Law and nothing in this agreement is intended to affect those rights. + b. Canada. If you acquired this software in Canada, you may stop receiving updates by turning off the automatic update feature, disconnecting your device from the Internet (if and when you re-connect to the Internet, however, the software will resume checking for and installing updates), or uninstalling the software. The product documentation, if any, may also specify how to turn off updates for your specific device or software. + c. Germany and Austria. + • Warranty. The properly licensed software will perform substantially as described in any Microsoft materials that accompany the software. However, Microsoft gives no contractual guarantee in relation to the licensed software. + • Limitation of Liability. In case of intentional conduct, gross negligence, claims based on the Product Liability Act, as well as, in case of death or personal or physical injury, Microsoft is liable according to the statutory law. + • Subject to the foregoing clause ii., Microsoft will only be liable for slight negligence if Microsoft is in breach of such material contractual obligations, the fulfillment of which facilitate the due performance of this agreement, the breach of which would endanger the purpose of this agreement and the compliance with which a party may constantly trust in (so-called "cardinal obligations"). In other cases of slight negligence, Microsoft will not be liable for slight negligence. + +12. DISCLAIMER OF WARRANTY. THE SOFTWARE IS LICENSED “AS IS.” YOU BEAR THE RISK OF USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES, OR CONDITIONS. TO THE EXTENT PERMITTED UNDER APPLICABLE LAWS, MICROSOFT EXCLUDES ALL IMPLIED WARRANTIES, INCLUDING MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -11. CONSUMER RIGHTS; REGIONAL VARIATIONS. This agreement describes certain legal rights. You may have other rights, including consumer rights, under the laws of your state or country. Separate and apart from your relationship with Microsoft, you may also have rights with respect to the party from which you acquired the software. This agreement does not change those other rights if the laws of your state or country do not permit it to do so. For example, if you acquired the software in one of the below regions, or mandatory country law applies, then the following provisions apply to you: - a. Australia. You have statutory guarantees under the Australian Consumer Law and nothing in this agreement is intended to affect those rights. - b. Canada. If you acquired this software in Canada, you may stop receiving updates by turning off the automatic update feature, disconnecting your device from the Internet (if and when you re-connect to the Internet, however, the software will resume checking for and installing updates), or uninstalling the software. The product documentation, if any, may also specify how to turn off updates for your specific device or software. - c. Germany and Austria. - • Warranty. The properly licensed software will perform substantially as described in any Microsoft materials that accompany the software. However, Microsoft gives no contractual guarantee in relation to the licensed software. - • Limitation of Liability. In case of intentional conduct, gross negligence, claims based on the Product Liability Act, as well as, in case of death or personal or physical injury, Microsoft is liable according to the statutory law. - • Subject to the foregoing clause ii., Microsoft will only be liable for slight negligence if Microsoft is in breach of such material contractual obligations, the fulfillment of which facilitate the due performance of this agreement, the breach of which would endanger the purpose of this agreement and the compliance with which a party may constantly trust in (so-called "cardinal obligations"). In other cases of slight negligence, Microsoft will not be liable for slight negligence. +13. DISCLAIMER. THIS SOFTWARE AND UNDERLYING SERVICES, ARE PROVIDED "AS-IS," "WITH ALL FAULTS," AND "AS AVAILABLE," AND ARE EXCLUDED FROM THE SERVICE LEVEL AGREEMENTS AND LIMITED WARRANTY. This software is not covered by customer support, and may be subject to reduced or different security, compliance and privacy commitments, as further explained in the Microsoft Privacy Statement, Microsoft Azure Trust Center, the Product Terms, the DPA, and any additional notices provided with the software. Where applicable, the following terms in the DPA do not apply to Previews: Processing of Personal Data; GDPR, Data Security. -12. DISCLAIMER OF WARRANTY. THE SOFTWARE IS LICENSED “AS IS.” YOU BEAR THE RISK OF USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES, OR CONDITIONS. TO THE EXTENT PERMITTED UNDER APPLICABLE LAWS, MICROSOFT EXCLUDES ALL IMPLIED WARRANTIES, INCLUDING MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +14. LIMITATION ON AND EXCLUSION OF DAMAGES. IF YOU HAVE ANY BASIS FOR RECOVERING DAMAGES DESPITE THE PRECEDING DISCLAIMER OF WARRANTY, YOU CAN RECOVER FROM MICROSOFT AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT, OR INCIDENTAL DAMAGES. -13. PRE-RELEASE DISCLAIMER. AS A PRE-RELEASE VERSION, THIS SOFTWARE AND UNDERLYING SERVICES, ARE PROVIDED "AS-IS," "WITH ALL FAULTS," AND "AS AVAILABLE," AND ARE EXCLUDED FROM THE SERVICE LEVEL AGREEMENTS AND LIMITED WARRANTY. Pre-release versions may not be covered by customer support, and may be subject to reduced or different security, compliance and privacy commitments, as further explained in the Microsoft Privacy Statement, Microsoft Azure Trust Center, the Product Terms, the DPA, and any additional notices provided with the software. Where applicable, the following terms in the DPA do not apply to Previews: Processing of Personal Data; GDPR, Data Security. + This limitation applies to (a) anything related to the software, services, content (including code) on third party Internet sites, or third party applications; and (b) claims for breach of contract, warranty, guarantee, or condition; strict liability, negligence, or other tort; or any other claim; in each case to the extent permitted by applicable law. -14. LIMITATION ON AND EXCLUSION OF DAMAGES. IF YOU HAVE ANY BASIS FOR RECOVERING DAMAGES DESPITE THE PRECEDING DISCLAIMER OF WARRANTY, YOU CAN RECOVER FROM MICROSOFT AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT, OR INCIDENTAL DAMAGES. + It also applies even if Microsoft knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your state, province, or country may not allow the exclusion or limitation of incidental, consequential, or other damages. - This limitation applies to (a) anything related to the software, services, content (including code) on third party Internet sites, or third party applications; and (b) claims for breach of contract, warranty, guarantee, or condition; strict liability, negligence, or other tort; or any other claim; in each case to the extent permitted by applicable law. - - It also applies even if Microsoft knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your state, province, or country may not allow the exclusion or limitation of incidental, consequential, or other damages. - - Please note: As this software is distributed in Canada, some of the clauses in this agreement are provided below in French. + Please note: As this software is distributed in Canada, some of the clauses in this agreement are provided below in French. - Remarque: Ce logiciel étant distribué au Canada, certaines des clauses dans ce contrat sont fournies ci-dessous en français. + Remarque: Ce logiciel étant distribué au Canada, certaines des clauses dans ce contrat sont fournies ci-dessous en français. - EXONÉRATION DE GARANTIE. Le logiciel visé par une licence est offert « tel quel ». Toute utilisation de ce logiciel est à votre seule risque et péril. Microsoft n’accorde aucune autre garantie expresse. Vous pouvez bénéficier de droits additionnels en vertu du droit local sur la protection des consommateurs, que ce contrat ne peut modifier. La ou elles sont permises par le droit locale, les garanties implicites de qualité marchande, d’adéquation à un usage particulier et d’absence de contrefaçon sont exclues. + EXONÉRATION DE GARANTIE. Le logiciel visé par une licence est offert « tel quel ». Toute utilisation de ce logiciel est à votre seule risque et péril. Microsoft n’accorde aucune autre garantie expresse. Vous pouvez bénéficier de droits additionnels en vertu du droit local sur la protection des consommateurs, que ce contrat ne peut modifier. La ou elles sont permises par le droit locale, les garanties implicites de qualité marchande, d’adéquation à un usage particulier et d’absence de contrefaçon sont exclues. - LIMITATION DES DOMMAGES-INTÉRÊTS ET EXCLUSION DE RESPONSABILITÉ POUR LES DOMMAGES. Vous pouvez obtenir de Microsoft et de ses fournisseurs une indemnisation en cas de dommages directs uniquement à hauteur de 5,00 $ US. Vous ne pouvez prétendre à aucune indemnisation pour les autres dommages, y compris les dommages spéciaux, indirects ou accessoires et pertes de bénéfices. + LIMITATION DES DOMMAGES-INTÉRÊTS ET EXCLUSION DE RESPONSABILITÉ POUR LES DOMMAGES. Vous pouvez obtenir de Microsoft et de ses fournisseurs une indemnisation en cas de dommages directs uniquement à hauteur de 5,00 $ US. Vous ne pouvez prétendre à aucune indemnisation pour les autres dommages, y compris les dommages spéciaux, indirects ou accessoires et pertes de bénéfices. - Cette limitation concerne: + Cette limitation concerne: - • tout ce qui est relié au logiciel, aux services ou au contenu (y compris le code) figurant sur des sites Internet tiers ou dans des programmes tiers; et + • tout ce qui est relié au logiciel, aux services ou au contenu (y compris le code) figurant sur des sites Internet tiers ou dans des programmes tiers; et - • les réclamations au titre de violation de contrat ou de garantie, ou au titre de responsabilité stricte, de négligence ou d’une autre faute dans la limite autorisée par la loi en vigueur. + • les réclamations au titre de violation de contrat ou de garantie, ou au titre de responsabilité stricte, de négligence ou d’une autre faute dans la limite autorisée par la loi en vigueur. - Elle s’applique également, même si Microsoft connaissait ou devrait connaître l’éventualité d’un tel dommage. Si votre pays n’autorise pas l’exclusion ou la limitation de responsabilité pour les dommages indirects, accessoires ou de quelque nature que ce soit, il se peut que la limitation ou l’exclusion ci-dessus ne s’appliquera pas à votre égard. + Elle s’applique également, même si Microsoft connaissait ou devrait connaître l’éventualité d’un tel dommage. Si votre pays n’autorise pas l’exclusion ou la limitation de responsabilité pour les dommages indirects, accessoires ou de quelque nature que ce soit, il se peut que la limitation ou l’exclusion ci-dessus ne s’appliquera pas à votre égard. - EFFET JURIDIQUE. Le présent contrat décrit certains droits juridiques. Vous pourriez avoir d’autres droits prévus par les lois de votre pays. Le présent contrat ne modifie pas les droits que vous confèrent les lois de votre pays si celles-ci ne le permettent pas. \ No newline at end of file + EFFET JURIDIQUE. Le présent contrat décrit certains droits juridiques. Vous pourriez avoir d’autres droits prévus par les lois de votre pays. Le présent contrat ne modifie pas les droits que vous confèrent les lois de votre pays si celles-ci ne le permettent pas. diff --git a/packages/live-share-react/README.md b/packages/live-share-react/README.md index 0207aba07..a9f4bbf58 100644 --- a/packages/live-share-react/README.md +++ b/packages/live-share-react/README.md @@ -14,32 +14,29 @@ import { LiveShareHost } from "@microsoft/teams-js"; const host = LiveShareHost.create(); export function LiveShareApp() { - // Call app.initialize() from teams-js before rendering LiveShareProvider + // Call app.initialize() from teams-js before rendering LiveShareProvider - return ( - - - - ); + return ( + + + + ); } // SharedCheckbox.jsx import { useSharedState } from "@microsoft/live-share-react"; export function SharedCheckbox() { - const [checked, setChecked] = useSharedState("MY-UNIQUE-ID", false); - return ( - { - setChecked(!checked); - }} - /> - ); + const [checked, setChecked] = useSharedState("MY-UNIQUE-ID", false); + return ( + { + setChecked(!checked); + }} + /> + ); } ``` @@ -102,31 +99,31 @@ The following example shows how `useSharedState` can be used to dynamically crea import { useSharedState } from "@microsoft/live-share-react"; export function CounterCard({ card, onDelete }) { - const [count, setCount, disposeCount] = useSharedState( - `card-count:${card.id}`, - 0 - ); - return ( -
        -

        {card.title}

        - - {`${count} `} - -
        - ); + const [count, setCount, disposeCount] = useSharedState( + `card-count:${card.id}`, + 0 + ); + return ( +
        +

        {card.title}

        + + {`${count} `} + +
        + ); } ``` @@ -143,32 +140,32 @@ import { useSharedMap } from "@microsoft/live-share-react"; import { v4 as uuid } from "uuid"; export function CardList() { - const { map, setEntry, deleteEntry } = useSharedMap("CUSTOM-MAP-ID"); - return ( -
        -

        {"Cards"}

        - -
        - {[...map.values()].map((cardValue) => ( - - ))} -
        -
        - ); + const { map, setEntry, deleteEntry } = useSharedMap("CUSTOM-MAP-ID"); + return ( +
        +

        {"Cards"}

        + +
        + {[...map.values()].map((cardValue) => ( + + ))} +
        +
        + ); } ``` @@ -270,34 +267,34 @@ Here is a simple example: import { useLiveEvent } from "@microsoft/live-share-react"; export function Reactions() { - const { latestEvent, sendEvent } = useLiveEvent("EVENT-ID"); + const { latestEvent, sendEvent } = useLiveEvent("EVENT-ID"); - return ( -
        - {/* Buttons for sending reactions */} - - - {/* Show latest reaction */} - {latestEvent?.local === false && ( -
        {`Received: ${latestEvent?.value.emoji}`}
        - )} - {latestEvent?.local === true && ( -
        {`Sent: ${latestEvent?.value.emoji}`}
        - )} -
        - ); + return ( +
        + {/* Buttons for sending reactions */} + + + {/* Show latest reaction */} + {latestEvent?.local === false && ( +
        {`Received: ${latestEvent?.value.emoji}`}
        + )} + {latestEvent?.local === true && ( +
        {`Sent: ${latestEvent?.value.emoji}`}
        + )} +
        + ); } ``` @@ -311,37 +308,38 @@ Here is a simple example: import { useLiveTimer } from "@microsoft/live-share-react"; export function CountdownTimer() { - const { milliRemaining, timerConfig, start, pause, play } = useLiveTimer("TIMER-ID"); + const { milliRemaining, timerConfig, start, pause, play } = + useLiveTimer("TIMER-ID"); - return ( -
        - - { timerConfig !== undefined && ( - - )} - { milliRemaining !== undefined && ( -

        - { `${Math.round(milliRemaining / 1000)} / ${Math.round(timerConfig.duration) / 1000}` } -

        - )} -
        - ); + return ( +
        + + {timerConfig !== undefined && ( + + )} + {milliRemaining !== undefined && ( +

        + {`${Math.round(milliRemaining / 1000)} / ${Math.round(timerConfig.duration) / 1000}`} +

        + )} +
        + ); } ``` @@ -359,24 +357,24 @@ import { useRef } from "react"; const ALLOWED_ROLES = [UserMeetingRole.organizer, UserMeetingRole.presenter]; const INITIAL_TRACK = - "https://storage.googleapis.com/media-session/big-buck-bunny/trailer.mov"; + "https://storage.googleapis.com/media-session/big-buck-bunny/trailer.mov"; export function VideoPlayer() { - const videoRef = useRef(null); - const { play, pause } = useMediaSynchronizer( - "MEDIA-SESSION-ID", - videoRef, - INITIAL_TRACK, - ALLOWED_ROLES - ); + const videoRef = useRef(null); + const { play, pause } = useMediaSynchronizer( + "MEDIA-SESSION-ID", + videoRef, + INITIAL_TRACK, + ALLOWED_ROLES + ); - return ( -
        -
        - ); + return ( +
        +
        + ); } ``` @@ -440,10 +438,7 @@ import { useTaskManager } from "@microsoft/live-share-react"; export const ExampleTaskManager = () => { const [taskId, setTaskId] = useState(undefined); - const { lockedTask } = useTaskManager( - "CUSTOM-TASK-MANAGER", - taskId, - ); + const { lockedTask } = useTaskManager("CUSTOM-TASK-MANAGER", taskId); const displayText = lockedTask ? "You are assigned the task" @@ -454,19 +449,19 @@ export const ExampleTaskManager = () => { {!taskId && ( )} {taskId && ( )}

        {displayText}

        @@ -477,7 +472,7 @@ export const ExampleTaskManager = () => { ### Custom Fluid object hooks -If you want to dynamically load a custom Fluid object in your app, use the `useDynamicDDS` to create a custom hook. This is the same hook that Live Share React uses internally within our custom hooks, such as `useLiveEvent`. If you made a custom data object or are using one of Fluid's experimental data structures, you also must register your Fluid `LoadableObjectClass` with `DynamicObjectRegistry.registerObjectClass` to `@microsoft/live-share`, if it is not already. +If you want to dynamically load a custom Fluid object in your app, use the `useDynamicDDS` to create a custom hook. This is the same hook that Live Share React uses internally within our custom hooks, such as `useLiveEvent`. If you made a custom data object or are using one of Fluid's experimental data structures, you also must register your Fluid `SharedObjectKind` with `DynamicObjectRegistry.registerObjectClass` to `@microsoft/live-share`, if it is not already. Implementations may vary for each dynamic object & hook. We will try and update this package periodically with new packages released by Fluid Framework and Live Share, as they are published. @@ -487,19 +482,25 @@ Example: import React from "react"; import { useDynamicDDS } from "@microsoft/live-share-react"; import { DynamicObjectRegistry } from "@microsoft/live-share"; -import { TaskManager } from "@fluid-experimental/task-manager"; +import { TaskManager } from "@fluid-experimental/task-manager"; // Register TaskManager as dynamic object -DynamicObjectRegistry.registerObjectClass(TaskManager, TaskManager.getFactory().type); +DynamicObjectRegistry.registerObjectClass( + TaskManager, + TaskManager.getFactory().type +); /** * A hook for joining a queue to lock tasks for a given id. Guaranteed to have only one user assigned to a task at a time. - * + * * @param uniqueKey the unique key for the TaskManager DDS * @param taskId the task id to lock * @returns stateful data about the status of the task lock */ -export const useTaskManager = (uniqueKey: string, taskId?: string): { +export const useTaskManager = ( + uniqueKey: string, + taskId?: string +): { lockedTask: boolean; taskManager: TaskManager | undefined; } => { @@ -515,7 +516,10 @@ export const useTaskManager = (uniqueKey: string, taskId?: string): { /** * User facing: dynamically load the TaskManager DDS for the given unique key. */ - const { dds: taskManager } = useDynamicDDS(uniqueKey, TaskManager); + const { dds: taskManager } = useDynamicDDS( + uniqueKey, + TaskManager + ); /** * When the task id changes, lock the task. When the task id is undefined, abandon the task. @@ -541,7 +545,7 @@ export const useTaskManager = (uniqueKey: string, taskId?: string): { currentTaskIdRef.current = undefined; } } - } + }; onLockTask(); } else if (!taskId && currentTaskIdRef.current) { taskManager.abandon(currentTaskIdRef.current); @@ -558,7 +562,7 @@ export const useTaskManager = (uniqueKey: string, taskId?: string): { taskManager?.abandon(currentTaskIdRef.current); } currentTaskIdRef.current = undefined; - } + }; }, [taskManager, taskId]); return { @@ -570,9 +574,9 @@ export const useTaskManager = (uniqueKey: string, taskId?: string): { ## Code samples -| Sample name | Description | Javascript | -| ----------------- | ----------------------------------------------------------------------- | ----------------------------------------------------- | -| Live Share React | Simple example with each of our custom Live Share React hooks. | [View](../../samples/javascript/04.live-share-react) | +| Sample name | Description | Javascript | +| ---------------- | -------------------------------------------------------------- | ---------------------------------------------------- | +| Live Share React | Simple example with each of our custom Live Share React hooks. | [View](../../samples/javascript/04.live-share-react) | ## React version compatibility @@ -584,9 +588,10 @@ The Live Share SDK contains dependencies for [@microsoft/teams-js](https://www.n **It is critical that your app use the package dependencies listed in the table below.** Lookup the version of the `@microsoft/live-share` you're using and set any other dependencies in your package.json file to match: -| @microsoft/live-share | @microsoft/teams-js | fluid-framework | @microsoft/live-share-\* | @fluidframework/azure-client | @microsoft/TeamsFx | @microsoft/TeamsFx-react | -| --------------------- | -------------------- | --------------- | -------------------------- | ---------------------------- | ------------------------------- | ------------------------------- | -| ^1.0.0 | ^2.11.0 | ^1.2.3 | ^1.0.0 | ^1.0.0 | ^2.5.0 | ^2.5.0 | +| @microsoft/live-share | @microsoft/teams-js | fluid-framework | @microsoft/live-share-\* | @fluidframework/azure-client | @microsoft/TeamsFx | @microsoft/TeamsFx-react | +| --------------------- | ------------------- | --------------- | ------------------------ | ---------------------------- | ------------------ | ------------------------ | +| ^2.0.0 | ^2.11.0 | ^2.0.0 | ^2.0.0 | ^2.0.0 | ^2.5.0 | ^2.5.0 | +| ^1.0.0 | ^2.11.0 | ^1.2.3 | ^1.0.0 | ^1.0.0 | ^2.5.0 | ^2.5.0 | ## Contributing diff --git a/packages/live-share-react/package.json b/packages/live-share-react/package.json index 83ad2942b..5739a5a86 100644 --- a/packages/live-share-react/package.json +++ b/packages/live-share-react/package.json @@ -1,51 +1,52 @@ { - "name": "@microsoft/live-share-react", - "version": "1.4.0-preview.0", - "description": "Build collaborative React apps using Microsoft's Fluid & Live Share frameworks with ease.", - "author": "Microsoft", - "license": "SEE LICENSE IN LICENSE", - "main": "./bin/index.js", - "types": "./bin/index.d.ts", - "scripts": { - "clean": "npx shx rm -rf bin", - "build": "tsc -p tsconfig.build.json", - "typecheck": "tsc" - }, - "dependencies": { - "@microsoft/live-share-turbo": "1.4.0-preview.0", - "url": "^0.11.0", - "uuid": "^9.0.0" - }, - "devDependencies": { - "@babel/core": "^7.21.8", - "@fluidframework/azure-client": "^1.1.1", - "@fluidframework/test-client-utils": "^1.3.6", - "@microsoft/live-share": "1.4.0", - "@microsoft/live-share-canvas": "1.4.0", - "@microsoft/live-share-media": "1.4.0", - "@types/react": "^18.0.0", - "@types/react-dom": "^18.0.0", - "@types/uuid": "^9.0.1", - "babel-loader": "^9.1.2", - "fluid-framework": "^1.3.6", - "typescript": "^5.0.4" - }, - "peerDependencies": { - "@fluidframework/azure-client": "^1.0.0", - "@microsoft/live-share": "1.4.0", - "@microsoft/live-share-canvas": "1.4.0", - "@microsoft/live-share-media": "1.4.0", - "fluid-framework": "^1.2.3", - "react": "^16.8.0 || ^17 || ^18", - "react-dom": "^16.8.0 || ^17 || ^18" - }, - "repository": { - "directory": "packages/live-share-react", - "type": "git", - "url": "https://github.com/microsoft/live-share-sdk" - }, - "homepage": "https://aka.ms/teamsliveshare", - "bugs": { - "url": "https://github.com/microsoft/live-share-sdk/issues" - } -} \ No newline at end of file + "name": "@microsoft/live-share-react", + "version": "2.0.0-internal.18", + "description": "Build collaborative React apps using Microsoft's Fluid & Live Share frameworks with ease.", + "author": "Microsoft", + "license": "SEE LICENSE IN LICENSE", + "type": "module", + "scripts": { + "clean": "npx shx rm -rf bin", + "build": "node ../../internal/build-tools/build-package.js --esm", + "typecheck": "tsc" + }, + "exports": { + "./package.json": "./package.json", + ".": { + "import": "./bin/esm/index.js" + } + }, + "dependencies": { + "url": "^0.11.0", + "uuid": "^9.0.0" + }, + "devDependencies": { + "@babel/core": "^7.21.8", + "@microsoft/live-share": "2.0.0-internal.18", + "@microsoft/live-share-canvas": "2.0.0-internal.18", + "@microsoft/live-share-media": "2.0.0-internal.18", + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.0", + "@types/uuid": "^9.0.1", + "babel-loader": "^9.1.2", + "fluid-framework": ">=2.40 <2.120", + "typescript": "~5.5.3" + }, + "peerDependencies": { + "@microsoft/live-share": "2.0.0-internal.18", + "@microsoft/live-share-canvas": "2.0.0-internal.18", + "@microsoft/live-share-media": "2.0.0-internal.18", + "fluid-framework": ">=2.40 <2.120", + "react": "^16.8.0 || ^17 || ^18", + "react-dom": "^16.8.0 || ^17 || ^18" + }, + "repository": { + "directory": "packages/live-share-react", + "type": "git", + "url": "https://github.com/microsoft/live-share-sdk" + }, + "homepage": "https://aka.ms/teamsliveshare", + "bugs": { + "url": "https://github.com/microsoft/live-share-sdk/issues" + } +} diff --git a/packages/live-share-react/src/index.ts b/packages/live-share-react/src/index.ts index 19226b3fd..c3f76676f 100644 --- a/packages/live-share-react/src/index.ts +++ b/packages/live-share-react/src/index.ts @@ -1,6 +1,6 @@ -export * from "./providers"; -export * from "./shared-hooks"; -export * from "./live-hooks"; -export * from "./types"; -export * from "./providers"; -export * from "./interfaces"; +export * from "./providers/index.js"; +export * from "./shared-hooks/index.js"; +export * from "./live-hooks/index.js"; +export * from "./types/index.js"; +export * from "./providers/index.js"; +export * from "./interfaces/index.js"; diff --git a/packages/live-share-react/src/interfaces/index.ts b/packages/live-share-react/src/interfaces/index.ts index d4515959b..8f0249724 100644 --- a/packages/live-share-react/src/interfaces/index.ts +++ b/packages/live-share-react/src/interfaces/index.ts @@ -1 +1 @@ -export * from "./LiveInterfaceExtensions"; +export * from "./LiveInterfaceExtensions.js"; diff --git a/packages/live-share-react/src/internal/index.ts b/packages/live-share-react/src/internal/index.ts index d14139239..76e27d1f3 100644 --- a/packages/live-share-react/src/internal/index.ts +++ b/packages/live-share-react/src/internal/index.ts @@ -1,2 +1,2 @@ -export * from "./errors"; -export * from "./type-guards"; +export * from "./errors.js"; +export * from "./type-guards.js"; diff --git a/packages/live-share-react/src/internal/type-guards.ts b/packages/live-share-react/src/internal/type-guards.ts index 0e1921757..6c991f718 100644 --- a/packages/live-share-react/src/internal/type-guards.ts +++ b/packages/live-share-react/src/internal/type-guards.ts @@ -1,4 +1,4 @@ -import { ITeamsJsSdkError } from "./errors"; +import { ITeamsJsSdkError } from "./errors.js"; /** * @hidden diff --git a/packages/live-share-react/src/live-hooks/index.ts b/packages/live-share-react/src/live-hooks/index.ts index 0ecdcc02b..19ad0602f 100644 --- a/packages/live-share-react/src/live-hooks/index.ts +++ b/packages/live-share-react/src/live-hooks/index.ts @@ -1,7 +1,7 @@ -export * from "./useLivePresence"; -export * from "./useLiveFollowMode"; -export * from "./useLiveState"; -export * from "./useMediaSynchronizer"; -export * from "./useLiveEvent"; -export * from "./useLiveCanvas"; -export * from "./useLiveTimer"; +export * from "./useLivePresence.js"; +export * from "./useLiveFollowMode.js"; +export * from "./useLiveState.js"; +export * from "./useMediaSynchronizer.js"; +export * from "./useLiveEvent.js"; +export * from "./useLiveCanvas.js"; +export * from "./useLiveTimer.js"; diff --git a/packages/live-share-react/src/live-hooks/useLiveCanvas.ts b/packages/live-share-react/src/live-hooks/useLiveCanvas.ts index 8096c944b..4629addb3 100644 --- a/packages/live-share-react/src/live-hooks/useLiveCanvas.ts +++ b/packages/live-share-react/src/live-hooks/useLiveCanvas.ts @@ -3,18 +3,16 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { - CanvasReferencePoint, - IBrush, - InkingManager, - InkingTool, - IPoint, - LiveCanvas, -} from "@microsoft/live-share-canvas"; +import { InkingManager, LiveCanvas } from "@microsoft/live-share-canvas"; import React from "react"; -import { useDynamicDDS } from "../shared-hooks"; -import { IUseLiveCanvasResults } from "../types"; -import { isRefObject } from "../utils"; +import { useDynamicDDS } from "../shared-hooks/index.js"; +import { + IUseLiveCanvasOptionalProps, + IUseLiveCanvasResults, +} from "../types/index.js"; +import { isRefObject } from "../utils/index.js"; +import { getRawNode } from "../shared-hooks/internals/tree-node-utils.js"; +import { LiveDataObjectInitializeState } from "@microsoft/live-share"; /** * React hook for using a Live Share Canvas `LiveCanvas` and `InkingManager`. @@ -26,27 +24,72 @@ import { isRefObject } from "../utils"; * * @param uniqueKey the unique key for the `LiveCanvas`. If one does not yet exist, a new one. * @param canvasElementRef the HTML div element ref or document ID that `InkingManager` will use for canvas-based collaboration. - * @param active Optional. Stateful boolean that will activate/de-activate `InkingManager` accordingly. - * @param tool Optional. Stateful enum for what tool to use in the `InkingManager`. - * @param lineBrush Optional. Stateful lineBrush object for the selected lineBrush options to use in `InkingManager`. - * @param offset Optional. Stateful offset point to use in the `InkingManager`. Gets the viewport offset. Defaults to 0,0. - * @param scale Optional. Stateful scale number to use in the `InkingManager`. Defaults to 1 and must be greater than 0. - * @param referencePoint Optional. Stateful reference point enum to use in the `InkingManger`. Defaults to "center". - * @param isCursorShared Optional. Stateful boolean flag for whether cursor should be shared in `LiveCanvas`. Defaults to false. - * @param localUserPictureUrl Optional. url string for the local user to display alongside their cursor. Defaults to undefined. - * @returns IUseLiveCanvasResults object that contains the `liveCanvas` data object and `inkingManager`. + * @param props Optional. Other optional props. + * @param props.active Optional. Stateful boolean that will activate/de-activate `InkingManager` accordingly. + * @param props.tool Optional. Stateful enum for what tool to use in the `InkingManager`. + * @param props.lineBrush Optional. Stateful lineBrush object for the selected lineBrush options to use in `InkingManager`. + * @param props.offset Optional. Stateful offset point to use in the `InkingManager`. Gets the viewport offset. Defaults to 0,0. + * @param props.scale Optional. Stateful scale number to use in the `InkingManager`. Defaults to 1 and must be greater than 0. + * @param props.referencePoint Optional. Stateful reference point enum to use in the `InkingManger`. Defaults to "center". + * @param props.isCursorShared Optional. Stateful boolean flag for whether cursor should be shared in `LiveCanvas`. Defaults to false. + * @param props.localUserPictureUrl Optional. url string for the local user to display alongside their cursor. Defaults to undefined. + * @param props.node Optional. A Fluid `LiveCanvasTree` `TreeNode` instance to swap out the underlying storage solution for strokes. + * To learn more, look at Fluid's [SharedTree](https://fluidframework.com/docs/data-structures/tree/) documentation. + * @param allowedRoles Optional. The user roles that are allowed to start/stop/pause the timer. + * + * @returns `IUseLiveCanvasResults` object that contains the `liveCanvas` data object and `inkingManager`. + * + * @example + ```jsx +import { useLiveCanvas } from "@microsoft/live-share-react"; +import { InkingTool } from "@microsoft/live-share-canvas"; +import { useRef } from "react"; + +// Unique identifier that distinguishes this useLiveCanvas from others in your app +const UNIQUE_KEY = "CUSTOM-LIVE-CANVAS"; + +// Example component +export function ExampleLiveCanvas() { + const liveCanvasRef = useRef(null); + const { liveCanvas, inkingManager } = useLiveCanvas( + "CUSTOM-LIVE-CANVAS", + liveCanvasRef, + ); + + return ( +
        +
        + {!!liveCanvas && ( +
        + + +
        + )} +
        + ); +}; + ``` */ export function useLiveCanvas( uniqueKey: string, canvasElementRef: React.RefObject | string, - active?: boolean, - tool?: InkingTool, - lineBrush?: IBrush, - offset?: IPoint, - scale?: number, - referencePoint?: CanvasReferencePoint, - isCursorShared?: boolean, - localUserPictureUrl?: string + props?: IUseLiveCanvasOptionalProps ): IUseLiveCanvasResults { /** * User facing: inking manager instance @@ -61,103 +104,132 @@ export function useLiveCanvas( LiveCanvas ); + // This should change less frequently then node if they are using `useTreeNode` + // We need the raw node anyways to apply event listeners + const rawNode = getRawNode(props?.node); + /** * Setup the InkingManager and LiveCanvas */ + React.useEffect( + () => { + // if the component is already listening or liveCanvas is not yet initialized, return + if (!liveCanvas) return; + // get the canvas element from the ref or document + let htmlElement: HTMLElement | null; + if (isRefObject(canvasElementRef)) { + htmlElement = canvasElementRef.current; + } else { + htmlElement = document.getElementById(canvasElementRef); + } + if (htmlElement === null) return; + // Clear out existing nodes + function removeAllChildren(node: HTMLElement | ChildNode) { + node.childNodes.forEach((childNode) => { + removeAllChildren(childNode); + childNode.remove(); + }); + } + removeAllChildren(htmlElement); + // Create the InkingManager and initialize the liveCanvas with it + const inkingManager = new InkingManager(htmlElement); + setInkingManager(inkingManager); + liveCanvas.initialize(inkingManager, props?.allowedRoles, rawNode); + + // cleanup function to be called when the component is unmount + return () => { + inkingManager.removeAllListeners(); + }; + }, + // Intentionally ommitting rawNode from deps because we only want to initialize once, + // whereas rawNode may change many times. + [liveCanvas, props?.allowedRoles] + ); + + /** + * Set the node if it changes while LiveCanvas is initialized + */ React.useEffect(() => { - // if the component is already listening or liveCanvas is not yet initialized, return - if (!liveCanvas) return; - // get the canvas element from the ref or document - let htmlElement: HTMLElement | null; - if (isRefObject(canvasElementRef)) { - htmlElement = canvasElementRef.current; - } else { - htmlElement = document.getElementById(canvasElementRef); - } - if (htmlElement === null) return; - // Create the InkingManager and initialize the liveCanvas with it - const inkingManager = new InkingManager(htmlElement); - setInkingManager(inkingManager); - liveCanvas.initialize(inkingManager); - - // cleanup function to be called when the component is unmount - return () => { - liveCanvas.dispose(); - inkingManager.removeAllListeners(); - }; - }, [liveCanvas]); + if ( + !rawNode || + liveCanvas?.initializeState !== + LiveDataObjectInitializeState.succeeded + ) + return; + liveCanvas.setTreeNode(rawNode); + }, [liveCanvas, rawNode]); /** * Activate or deactivate the inkingManager based on the 'active' prop */ React.useEffect(() => { - if (inkingManager && active !== undefined) { - if (active) { + if (inkingManager && props?.active !== undefined) { + if (props?.active) { inkingManager.activate(); } else { inkingManager.deactivate(); } } - }, [active, inkingManager]); + }, [props?.active, inkingManager]); /** * Sets the tool of the inkingManager based on the 'tool' prop */ React.useEffect(() => { - if (inkingManager && tool !== undefined) { - inkingManager.tool = tool; + if (inkingManager && props?.tool !== undefined) { + inkingManager.tool = props.tool; } - }, [tool, inkingManager]); + }, [props?.tool, inkingManager]); /** * Sets the offset of the inkingManager based on the 'offset' prop */ React.useEffect(() => { - if (inkingManager && offset !== undefined) { + if (inkingManager && props?.offset !== undefined) { inkingManager.offset = { - x: offset.x, - y: offset.y, + x: props?.offset.x, + y: props?.offset.y, }; } - }, [offset?.x, offset?.y, inkingManager]); + }, [props?.offset?.x, props?.offset?.y, inkingManager]); /** * Sets the scale of the inkingManager based on the 'scale' prop */ React.useEffect(() => { - if (inkingManager && scale !== undefined) { - inkingManager.scale = scale; + if (inkingManager && props?.scale !== undefined) { + inkingManager.scale = props?.scale; } - }, [scale, inkingManager]); + }, [props?.scale, inkingManager]); /** * Sets the referencePoint of the inkingManager based on the 'referencePoint' prop */ React.useEffect(() => { - if (inkingManager && referencePoint !== undefined) { - inkingManager.referencePoint = referencePoint; + if (inkingManager && props?.referencePoint !== undefined) { + inkingManager.referencePoint = props?.referencePoint; } - }, [referencePoint, inkingManager]); + }, [props?.referencePoint, inkingManager]); /** * Sets the lineBrush of the inkingManager based on the 'lineBrush' prop */ React.useEffect(() => { - if (inkingManager && lineBrush) { + if (inkingManager && props?.lineBrush) { inkingManager.lineBrush = { - color: lineBrush.color, - tip: lineBrush.tip, - tipSize: lineBrush.tipSize, - type: lineBrush.type, - endArrow: lineBrush.endArrow, + color: props.lineBrush.color, + tip: props.lineBrush.tip, + tipSize: props.lineBrush.tipSize, + type: props.lineBrush.type, + endArrow: props.lineBrush.endArrow, }; } }, [ - lineBrush?.color, - lineBrush?.tip, - lineBrush?.tipSize, - lineBrush?.type, - lineBrush?.endArrow, + props?.lineBrush?.color, + props?.lineBrush?.tip, + props?.lineBrush?.tipSize, + props?.lineBrush?.type, + props?.lineBrush?.endArrow, inkingManager, ]); @@ -165,21 +237,21 @@ export function useLiveCanvas( * Sets the isCursorShared of the liveCanvas based on the 'isCursorShared' prop */ React.useEffect(() => { - if (liveCanvas && isCursorShared !== undefined) { - liveCanvas.isCursorShared = isCursorShared; + if (liveCanvas && props?.isCursorShared !== undefined) { + liveCanvas.isCursorShared = props.isCursorShared; } - }, [isCursorShared, liveCanvas]); + }, [props?.isCursorShared, liveCanvas]); /** * Sets the onGetLocalUserInfo method of the liveCanvas based on the 'localUserCursor' prop */ React.useEffect(() => { - if (liveCanvas && localUserPictureUrl) { + if (liveCanvas && props?.localUserPictureUrl) { liveCanvas.onGetLocalUserPictureUrl = (): string | undefined => { - return localUserPictureUrl; + return props.localUserPictureUrl; }; } - }, [localUserPictureUrl, liveCanvas]); + }, [props?.localUserPictureUrl, liveCanvas]); /** * Return hook response diff --git a/packages/live-share-react/src/live-hooks/useLiveEvent.ts b/packages/live-share-react/src/live-hooks/useLiveEvent.ts index 6d4fb5b31..a8eac5d49 100644 --- a/packages/live-share-react/src/live-hooks/useLiveEvent.ts +++ b/packages/live-share-react/src/live-hooks/useLiveEvent.ts @@ -14,15 +14,15 @@ import { IUseLiveEventResults, OnReceivedLiveEventAction, SendLiveEventAction, -} from "../types"; -import { IReceiveLiveEvent } from "../interfaces"; -import { useDynamicDDS } from "../shared-hooks"; +} from "../types/index.js"; +import { IReceiveLiveEvent } from "../interfaces/index.js"; +import { useDynamicDDS } from "../shared-hooks/index.js"; import { ActionContainerNotJoinedError, ActionLiveDataObjectInitializedError, ActionLiveDataObjectUndefinedError, -} from "../internal"; -import { useFluidObjectsContext } from "../providers"; +} from "../internal/index.js"; +import { useFluidObjectsContext } from "../providers/index.js"; /** * React hook for using a Live Share `LiveEvent`. @@ -38,6 +38,42 @@ import { useFluidObjectsContext } from "../providers"; * @param allowedRoles Optional. The meeting roles eligible to send events through this object. * @param onReceivedEvent Optional. Callback method to be called when a new notification is received. * @returns stateful `latestEvent` & `allEvents` list, `sendEvent` callback, and the `liveEvent` object. + * + * @example + ```jsx +import { useLiveEvent } from "@microsoft/live-share-react"; + +const emojis = ["❤️", "😂", "👍", "👎"]; + +// Define a unique key that differentiates this usage of `useLiveEvent` from others in your app +const MY_UNIQUE_KEY = "event-key"; + +// Example component for using useLiveEvent +export const MyCustomEvent = () => { + const { latestEvent, liveEvent, sendEvent } = useLiveEvent(MY_UNIQUE_KEY); + + // Render loading UI when creating LiveEvent instance for first time + if (!liveEvent) return <>Loading...; + + // Render UI + return ( +
        + {`Latest event: ${latestEvent?.value}, from local user: ${latestEvent?.local}`} + {"Select a planet below:"} + {emojis.map((emoji) => ( + + ))} +
        + ); +}; + ``` */ export function useLiveEvent( uniqueKey: string, @@ -68,7 +104,7 @@ export function useLiveEvent( * User facing: callback to send event through `LiveEvent` */ const sendEvent: SendLiveEventAction = React.useCallback( - async (event: TEvent) => { + async (event: TEvent, targetClientId?: string) => { if (!container) { throw new ActionContainerNotJoinedError( "liveEvent", @@ -87,7 +123,7 @@ export function useLiveEvent( "sendEvent" ); } - return await liveEvent.send(event); + return await liveEvent.send(event, targetClientId); }, [container, liveEvent] ); diff --git a/packages/live-share-react/src/live-hooks/useLiveFollowMode.ts b/packages/live-share-react/src/live-hooks/useLiveFollowMode.ts index 0f86b4ab8..8a1e6e28b 100644 --- a/packages/live-share-react/src/live-hooks/useLiveFollowMode.ts +++ b/packages/live-share-react/src/live-hooks/useLiveFollowMode.ts @@ -12,14 +12,14 @@ import { IFollowModeState, } from "@microsoft/live-share"; import React from "react"; -import { useDynamicDDS } from "../shared-hooks"; -import { useFluidObjectsContext } from "../providers"; +import { useDynamicDDS } from "../shared-hooks/index.js"; +import { useFluidObjectsContext } from "../providers/index.js"; import { ActionContainerNotJoinedError, ActionLiveDataObjectInitializedError, ActionLiveDataObjectUndefinedError, -} from "../internal"; -import { IUseLiveFollowModeResults } from "../types"; +} from "../internal/index.js"; +import { IUseLiveFollowModeResults } from "../types/index.js"; /** * React hook for using a Live Share `LiveFollowMode`. @@ -36,6 +36,145 @@ import { IUseLiveFollowModeResults } from "../types"; * @param initialData The initial value for the local user's `stateValue`. * @param allowedRoles Optional. The user roles that are allowed to present to use `startPresenting()` or `stopPresenting()`. * @returns `IUseLiveFollowModeResults` results, which contains React stateful objects and callbacks. + * + * @example + ```jsx + import { FollowModeType } from "@microsoft/live-share"; +import { useLiveFollowMode } from "@microsoft/live-share-react"; +// As an example, we will use a fake component to denote what a 3D viewer might look like in an app +import { Example3DModelViewer } from "./components"; + +// Define a unique key that differentiates this usage of `useLiveFollowMode` from others in your app +const MY_UNIQUE_KEY = "follow-mode-key"; + +// Define the initial stateValue for the local user (optional). +const startingCameraPosition = { + x: 0, + y: 0, + z: 0, +}; + +// Example component for using useLiveFollowMode +export function MyLiveFollowMode() { + const { + state, + localUser, + otherUsers, + allUsers, + liveFollowMode, + update, + startPresenting, + stopPresenting, + beginSuspension, + endSuspension, + followUser, + stopFollowing, + } = useLiveFollowMode(MY_UNIQUE_KEY, startingCameraPosition); + + // Example of an event listener for a camera position changed event. + // For something like a camera change event, you should use a debounce function. + function onCameraPositionChanged(position, isUserAction) { + // Broadcast change to other users so that they have their latest camera position + update(position); + // If the local user changed the position while following another user, we want to suspend. + // Note: helps to distinguish changes initiated by the local user (e.g., drag mouse) separately from other change events. + if (!isUserAction) return; + switch (state.type) { + case FollowModeType.followPresenter: + case FollowModeType.followUser: { + // This will trigger a "stateChanged" event update for the local user only. + followMode.beginSuspension(); + break; + } + default: { + // No need to suspend for other types + break; + } + } + } + + // Can optionally get the relevant user's presence object + const followingUser = liveFollowMode?.getUser(state.followingUserId); + + // Render loading UI when creating LiveFollowMode instance for first time + if (!liveFollowMode) return <>Loading...; + + // Render UI + return ( +
        + {state.type === FollowModeType.local && ( +
        +

        {""}

        + +
        + )} + {state.type === FollowModeType.activeFollowers && ( +
        +

        {`${state.otherUsersCount} users are following you`}

        + +
        + )} + {state.type === FollowModeType.activePresenter && ( +
        +

        {`You are actively presenting to everyone`}

        + +
        + )} + {state.type === FollowModeType.followPresenter && ( +
        +

        {`${followingUser?.displayName} is presenting to everyone`}

        + +
        + )} + {state.type === FollowModeType.suspendFollowPresenter && ( +
        +

        {`${followingUser?.displayName} is presenting to everyone`}

        + +
        + )} + {state.type === FollowModeType.followUser && ( +
        +

        {`You are following ${followingUser?.displayName}`}

        + +
        + )} + {state.type === FollowModeType.suspendFollowUser && ( +
        +

        {`You were following ${followingUser?.displayName}`}

        + +
        + )} +
        +

        {"Follow a specific user:"}

        + {otherUsers.map((user) => ( + + ))} +
        + +
        + ); +}; + ``` */ export function useLiveFollowMode( uniqueKey: string, @@ -63,12 +202,16 @@ export function useLiveFollowMode( /** * User facing: list of non-local user's presence objects. */ - const otherUsers = allUsers.filter((user) => !user.isLocalUser); + const otherUsers = React.useMemo(() => { + return allUsers.filter((user) => !user.isLocalUser); + }, [allUsers]); /** * User facing: local user's presence object. */ - const localUser = allUsers.find((user) => user.isLocalUser); + const localUser = React.useMemo(() => { + return allUsers.find((user) => user.isLocalUser); + }, [allUsers]); const { container } = useFluidObjectsContext(); diff --git a/packages/live-share-react/src/live-hooks/useLivePresence.ts b/packages/live-share-react/src/live-hooks/useLivePresence.ts index a2bfb552e..1cb6ef2c2 100644 --- a/packages/live-share-react/src/live-hooks/useLivePresence.ts +++ b/packages/live-share-react/src/live-hooks/useLivePresence.ts @@ -5,20 +5,24 @@ import { LivePresenceUser, - PresenceState, LivePresence, UserMeetingRole, LiveDataObjectInitializeState, + LivePresenceData, + PresenceStatus, } from "@microsoft/live-share"; import React from "react"; -import { IUseLivePresenceResults, OnUpdateLivePresenceAction } from "../types"; -import { useDynamicDDS } from "../shared-hooks"; -import { useFluidObjectsContext } from "../providers"; +import { + IUseLivePresenceResults, + OnUpdateLivePresenceAction, +} from "../types/index.js"; +import { useDynamicDDS } from "../shared-hooks/index.js"; +import { useFluidObjectsContext } from "../providers/index.js"; import { ActionContainerNotJoinedError, ActionLiveDataObjectInitializedError, ActionLiveDataObjectUndefinedError, -} from "../internal"; +} from "../internal/index.js"; /** * React hook for using a Live Share `LivePresence`. @@ -31,17 +35,66 @@ import { * * @template TData Optional typing for the custom user presence data object. Default is `object` type. * @param uniqueKey The unique key for `LivePresence`. If one does not yet exist, a new one will be created. - * @param initialData Optional. Initial presence data object for the user. Can be value or a function to get the value. - * @param initialPresenceState Optional. Initial status of the user's presence. Default is online. + * @param initialData Initial presence data object for the user. Can be value or a function to get the value. * @param allowedRoles Optional. the user roles that are allowed to mutate the synchronized state * will be created, otherwise it will use the existing one. Default value is ":" * @returns stateful `localUser`, `otherUsers` list, and `allUsers` list. Also returns a callback method * to update the local user's presence and the `LivePresence` Fluid object. + * + * @example + ```jsx +import { useLivePresence } from "@microsoft/live-share-react"; + +// Define a unique key that differentiates this usage of `useLivePresence` from others in your app +const MY_UNIQUE_KEY = "presence-key"; + +// Example component for using useLivePresence +export const MyCustomPresence = () => { + const { + allUsers, + localUser, + livePresence, + updatePresence, + } = useLivePresence(MY_UNIQUE_KEY, { + picture: "DEFAULT_PROFILE_PICTURE_URL", + readyToStart: false, + }); + + // Callback to update the user's presence + const onToggleReady = () => { + updatePresence({ + ...localUser.data, + readyToStart: !localUser.data.readyToStart, + }); + } + + // Render loading UI while loading LivePresence for first time + if (!livePresence) return <>Loading...; + + // Render presence UI + return ( + {allUsers.map((user) => ( +
        +
        + {user.displayName} +
        +
        + {`Ready: ${user.data.readyToStart}`} +
        + {user.isLocalUser && ( + + )} +
        + ))} + ); +} + ``` */ -export function useLivePresence( +export function useLivePresence( uniqueKey: string, - initialData?: TData | (() => TData) | undefined, - initialPresenceState: PresenceState = PresenceState.online, + initialData: TData | (() => TData), allowedRoles?: UserMeetingRole[] ): IUseLivePresenceResults { /** @@ -55,18 +108,26 @@ export function useLivePresence( */ const { dds: livePresence } = useDynamicDDS>( uniqueKey, - LivePresence + LivePresence ); /** * User facing: list of non-local user's presence objects. */ - const otherUsers = allUsers.filter((user) => !user.isLocalUser); + const otherUsers = React.useMemo(() => { + return allUsers.filter((user) => !user.isLocalUser); + }, [allUsers]); /** * User facing: local user's presence object. */ - const localUser = allUsers.find((user) => user.isLocalUser); + const localUser = React.useMemo(() => { + return allUsers.find((user) => user.isLocalUser); + }, [allUsers]); + + const onlineUsers = React.useMemo(() => { + return allUsers.filter((user) => user.status === PresenceStatus.online); + }, [allUsers]); const { container } = useFluidObjectsContext(); @@ -74,7 +135,7 @@ export function useLivePresence( * User facing: callback to update the local user's presence. */ const updatePresence: OnUpdateLivePresenceAction = React.useCallback( - async (data?: TData | undefined, state?: PresenceState | undefined) => { + async (data: TData) => { if (!container) { throw new ActionContainerNotJoinedError( "livePresence", @@ -93,7 +154,7 @@ export function useLivePresence( "updatePresence" ); } - return await livePresence.update(data, state); + return await livePresence.update(data); }, [container, livePresence] ); @@ -121,7 +182,6 @@ export function useLivePresence( isInitialDataCallback(initialData) ? initialData() : initialData, - initialPresenceState, allowedRoles ); } @@ -136,11 +196,14 @@ export function useLivePresence( localUser, otherUsers, allUsers, + onlineUsers, livePresence, updatePresence, }; } -function isInitialDataCallback(value: any): value is () => TData { +function isInitialDataCallback( + value: any +): value is () => TData { return typeof value === "function"; } diff --git a/packages/live-share-react/src/live-hooks/useLiveState.ts b/packages/live-share-react/src/live-hooks/useLiveState.ts index ee6e37794..406a7616f 100644 --- a/packages/live-share-react/src/live-hooks/useLiveState.ts +++ b/packages/live-share-react/src/live-hooks/useLiveState.ts @@ -9,15 +9,15 @@ import { UserMeetingRole, } from "@microsoft/live-share"; import React from "react"; -import { SetLiveStateAction } from "../types"; -import { useDynamicDDS } from "../shared-hooks"; -import { useFluidObjectsContext } from "../providers"; +import { SetLiveStateAction } from "../types/index.js"; +import { useDynamicDDS } from "../shared-hooks/index.js"; +import { useFluidObjectsContext } from "../providers/index.js"; import { ActionContainerNotJoinedError, ActionLiveDataObjectInitializedError, ActionLiveDataObjectUndefinedError, isPrevStateCallback, -} from "../internal"; +} from "../internal/index.js"; /** * React hook for using a Live Share `LiveState`. @@ -31,6 +31,51 @@ import { * @param allowedRoles Optional. the user roles that are allowed to mutate the synchronized state * @returns ordered values: first value is the synchronized state value and the second is a setter to change the state value. * The setter returns a void promise, which will throw if the user does not have the required roles to set. + * + * @example + ```jsx +import { useLiveState } from "@microsoft/live-share-react"; + +const planets = [ + "Mercury", + "Venus", + "Earth", + "Mars", + "Jupiter", + "Saturn", + "Uranus", + "Neptune", +]; + +// Define a unique key that differentiates this usage of `useLiveState` from others in your app +const MY_UNIQUE_KEY = "selected-planet-key"; + +// Example component for using useLiveState +export const MyCustomState = () => { + const [planet, setPlanet, liveState] = useLiveState(MY_UNIQUE_KEY, planets[0]); + + // Render loading UI when creating LiveState instance for first time + if (!liveState) return <>Loading...; + + // Render UI + return ( +
        + {`Current planet: ${planet}`} + {"Select a planet below:"} + {planets.map((planet) => ( + + ))} +
        + ); +}; + ``` */ export function useLiveState( uniqueKey: string, @@ -95,9 +140,12 @@ export function useLiveState( if ( liveState.initializeState === LiveDataObjectInitializeState.needed ) { - liveState.initialize(initialState, allowedRoles); + liveState + .initialize(initialState, allowedRoles) + .then(() => onStateChanged(liveState.state)); + } else { + onStateChanged(liveState.state); } - onStateChanged(liveState.state); return () => { liveState?.off("stateChanged", onStateChanged); diff --git a/packages/live-share-react/src/live-hooks/useLiveTimer.ts b/packages/live-share-react/src/live-hooks/useLiveTimer.ts index b6879e0d2..402119a46 100644 --- a/packages/live-share-react/src/live-hooks/useLiveTimer.ts +++ b/packages/live-share-react/src/live-hooks/useLiveTimer.ts @@ -21,14 +21,14 @@ import { OnTimerDidPlayAction, OnTimerDidStartAction, OnTimerTickAction, -} from "../types"; -import { useDynamicDDS } from "../shared-hooks"; -import { useFluidObjectsContext } from "../providers"; +} from "../types/index.js"; +import { useDynamicDDS } from "../shared-hooks/index.js"; +import { useFluidObjectsContext } from "../providers/index.js"; import { ActionContainerNotJoinedError, ActionLiveDataObjectInitializedError, ActionLiveDataObjectUndefinedError, -} from "../internal"; +} from "../internal/index.js"; /** * React hook for using Live Share's `LiveTimer` DDS. @@ -46,6 +46,61 @@ import { * @param onPlay Optional. event handler callback for when the timer is resumed. * @param onFinish Optional. event handler callback for when the timer finishes. * @returns results and callbacks exposed via the hook. + * + * @example + ```jsx +import { useLiveTimer } from "@microsoft/live-share-react"; + +// Define a unique key that differentiates this usage of `useLiveTimer` from others in your app +const MY_UNIQUE_KEY = "timer-key"; + +// Example component for using useLiveTimer +export function CountdownTimer() { + const { + milliRemaining, + timerConfig, + liveTimer, + start, + pause, + play, + } = useLiveTimer("TIMER-ID"); + + // Render loading UI when creating LiveTimer instance for first time + if (!liveTimer) return <>Loading...; + + return ( +
        + + {timerConfig !== undefined && ( + + )} + {milliRemaining !== undefined && ( +

        + {`${Math.round(milliRemaining / 1000)} / ${ + Math.round(timerConfig.duration) / 1000 + }`} +

        + )} +
        + ); +} + ``` */ export function useLiveTimer( uniqueKey: string, diff --git a/packages/live-share-react/src/live-hooks/useMediaSynchronizer.ts b/packages/live-share-react/src/live-hooks/useMediaSynchronizer.ts index 263f723dc..a35cd1f9b 100644 --- a/packages/live-share-react/src/live-hooks/useMediaSynchronizer.ts +++ b/packages/live-share-react/src/live-hooks/useMediaSynchronizer.ts @@ -16,14 +16,18 @@ import { MediaPlayerSynchronizer, MediaSessionCoordinatorSuspension, } from "@microsoft/live-share-media"; -import { isExtendedMediaMetadata, isMediaElement, isRefObject } from "../utils"; -import { useDynamicDDS } from "../shared-hooks"; -import { IUseMediaSynchronizerResults } from "../types"; -import { useFluidObjectsContext } from "../providers"; +import { + isExtendedMediaMetadata, + isMediaElement, + isRefObject, +} from "../utils/index.js"; +import { useDynamicDDS } from "../shared-hooks/index.js"; +import { IUseMediaSynchronizerResults } from "../types/index.js"; +import { useFluidObjectsContext } from "../providers/index.js"; import { ActionContainerNotJoinedError, ActionLiveDataObjectUndefinedError, -} from "../internal"; +} from "../internal/index.js"; /** * React hook for using a Live Share media `MediaPlayerSynchronizer`. @@ -39,6 +43,67 @@ import { * @param viewOnly Optional. Flag for whether or not the media synchronizer should be in viewOnly mode. * @param canSendPositionUpdates Optional. Controls whether or not the local client is allowed to send position updates to the group. * @returns IUseMediaSynchronizerResults object. + * + * @example + ```jsx +import { useMediaSynchronizer } from "@microsoft/live-share-react"; +import { UserMeetingRole } from "@microsoft/live-share"; +import { MediaPlayerSynchronizerEvents } from "@microsoft/live-share-media"; +import { useRef, useEffect } from "react"; + +const ALLOWED_ROLES = [UserMeetingRole.organizer, UserMeetingRole.presenter]; + +const INITIAL_TRACK = ""; + +// Define a unique key that distinguishes this `useMediaSynchronizer` from others in your app +const UNIQUE_KEY = "MEDIA-SESSION-ID"; + +export function VideoPlayer() { + const videoRef = useRef(null); + const { play, pause, seekTo, mediaSynchronizer } = useMediaSynchronizer( + UNIQUE_KEY, + videoRef, + INITIAL_TRACK, + ALLOWED_ROLES + ); + + // Listen for groupaction events (optional) + useEffect(() => { + // Listen for player group actions for errors (e.g., play error) + const onGroupAction = (evt: IMediaPlayerSynchronizerEvent) => { + // See which user made the change (e.g., to display a notification) + const clientInfo = await synchronizer.mediaSession.getClientInfo(evt.details.clientId); + }; + mediaSynchronizer?.addEventListener( + MediaPlayerSynchronizerEvents.groupaction, + onGroupAction + ); + return () => { + mediaSynchronizer?.removeEventListener( + MediaPlayerSynchronizerEvents.groupaction, + onGroupAction + ); + }; + }, [mediaSynchronizer]); + + return ( +
        +
        + ); +} + ``` */ export function useMediaSynchronizer( uniqueKey: string, diff --git a/packages/live-share-react/src/providers/AzureProvider.tsx b/packages/live-share-react/src/providers/AzureProvider.tsx index 4c55e3ef0..f0f08a962 100644 --- a/packages/live-share-react/src/providers/AzureProvider.tsx +++ b/packages/live-share-react/src/providers/AzureProvider.tsx @@ -3,21 +3,19 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { IFluidContainer, LoadableObjectClassRecord } from "fluid-framework"; +import { ContainerSchema, IFluidContainer } from "fluid-framework"; import React from "react"; import { AzureClientProps, AzureContainerServices, } from "@fluidframework/azure-client"; -import { IAzureContainerResults } from "../types"; +import { IAzureContainerResults } from "../types/index.js"; import { ISharedStateRegistryResponse, useSharedStateRegistry, -} from "../shared-hooks"; -import { - AzureTurboClient, - IFluidTurboClient, -} from "@microsoft/live-share-turbo"; +} from "../shared-hooks/index.js"; +import { AzureLiveShareClient } from "@microsoft/live-share"; +import { BaseLiveShareClient } from "@microsoft/live-share/internal"; /** * React Context provider values for `` and ``. @@ -29,7 +27,7 @@ export interface IFluidContext extends ISharedStateRegistryResponse { /** * The Fluid Turbo client used for connecting to the Fluid container. */ - clientRef: React.MutableRefObject; + clientRef: React.MutableRefObject; /** * Stateful Fluid container. */ @@ -54,7 +52,7 @@ export interface IFluidContext extends ISharedStateRegistryResponse { */ getContainer: ( containerId: string, - initialObjects?: LoadableObjectClassRecord + fluidContainerSchema?: ContainerSchema ) => Promise; /** * React callback function to create and connect to a new Fluid container. @@ -67,7 +65,7 @@ export interface IFluidContext extends ISharedStateRegistryResponse { * @returns promise that returns a results object once complete (e.g., container, services, etc.) */ createContainer: ( - initialObjects?: LoadableObjectClassRecord, + fluidContainerSchema?: ContainerSchema, onInitializeContainer?: (container: IFluidContainer) => void ) => Promise; } @@ -125,9 +123,9 @@ export interface IAzureProviderProps { */ createOnLoad?: boolean; /** - * The initial object schema to use when {@link joinOnLoad} or {@link createOnLoad} is true. + * The initial schema to use when {@link joinOnLoad} or {@link createOnLoad} is true. */ - initialObjects?: LoadableObjectClassRecord; + fluidContainerSchema?: ContainerSchema; /** * Flag to control whether or not to connect to an existing container on first mount. * @@ -142,8 +140,8 @@ export interface IAzureProviderProps { */ export const AzureProvider: React.FC = (props) => { const startedRef = React.useRef(false); - const clientRef = React.useRef( - new AzureTurboClient(props.clientOptions) + const clientRef = React.useRef( + new AzureLiveShareClient(props.clientOptions) ); const [results, setResults] = React.useState< IAzureContainerResults | undefined @@ -158,14 +156,14 @@ export const AzureProvider: React.FC = (props) => { const getContainer = React.useCallback( async ( containerId: string, - initialObjects?: LoadableObjectClassRecord + fluidContainerSchema?: ContainerSchema ): Promise => { return new Promise(async (resolve, reject) => { try { const results: IAzureContainerResults = await clientRef.current.getContainer( containerId, - initialObjects + fluidContainerSchema ); setResults(results); resolve(results); @@ -185,13 +183,15 @@ export const AzureProvider: React.FC = (props) => { */ const createContainer = React.useCallback( async ( - initialObjects?: LoadableObjectClassRecord, + fluidContainerSchema?: ContainerSchema, onInitializeContainer?: (container: IFluidContainer) => void ): Promise => { return new Promise(async (resolve, reject) => { try { const results: IAzureContainerResults = - await clientRef.current.createContainer(initialObjects); + await clientRef.current.createContainer( + fluidContainerSchema + ); if (onInitializeContainer) { onInitializeContainer(results.container); } @@ -225,16 +225,16 @@ export const AzureProvider: React.FC = (props) => { return; startedRef.current = true; if (props.containerId && props.joinOnLoad) { - getContainer(props.containerId, props.initialObjects); + getContainer(props.containerId, props.fluidContainerSchema); } else if (!props.containerId && props.createOnLoad) { - createContainer(props.initialObjects); + createContainer(props.fluidContainerSchema); } }, [ results?.container?.connectionState, props.containerId, props.createOnLoad, props.joinOnLoad, - props.initialObjects, + props.fluidContainerSchema, getContainer, createContainer, ]); diff --git a/packages/live-share-react/src/providers/LiveShareProvider.tsx b/packages/live-share-react/src/providers/LiveShareProvider.tsx index fb918f3cf..c87677242 100644 --- a/packages/live-share-react/src/providers/LiveShareProvider.tsx +++ b/packages/live-share-react/src/providers/LiveShareProvider.tsx @@ -3,18 +3,18 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { IFluidContainer, LoadableObjectClassRecord } from "fluid-framework"; +import { ContainerSchema, IFluidContainer } from "fluid-framework"; import React from "react"; -import { useSharedStateRegistry } from "../shared-hooks"; +import { useSharedStateRegistry } from "../shared-hooks/index.js"; import { ILiveShareClientOptions, ILiveShareHost, ILiveShareJoinResults, ITimestampProvider, + LiveShareClient, } from "@microsoft/live-share"; -import { FluidContext, useFluidObjectsContext } from "./AzureProvider"; -import { LiveShareTurboClient } from "@microsoft/live-share-turbo"; -import { isITeamsJsSdkError } from "../internal"; +import { FluidContext, useFluidObjectsContext } from "./AzureProvider.js"; +import { isITeamsJsSdkError } from "../internal/index.js"; /** * React Context provider values for ``. @@ -52,7 +52,7 @@ export interface ILiveShareContext { * @returns Promise with `ILiveShareJoinResults`, which includes the Fluid container */ join: ( - initialObjects?: LoadableObjectClassRecord, + fluidContainerSchema?: ContainerSchema, onInitializeContainer?: (container: IFluidContainer) => void ) => Promise; } @@ -72,6 +72,57 @@ export const LiveShareContext = React.createContext( * See `useFluidObjectsContext` for other information related to the Live Share session, such as the `container`. * * @returns current state of `LiveShareContext` + * + * @example + ```jsx +// LiveShareApp.jsx +import { LiveShareProvider } from "@microsoft/live-share-react"; +import { LiveShareHost } from "@microsoft/teams-js"; + +const host = LiveShareHost.create(); + +export function LiveShareApp() { + // Call app.initialize() from teams-js before rendering LiveShareProvider + + return ( + + + + + + ); +} + +// LiveShareLoader.jsx +import { useLiveShareContext } from "@microsoft/live-share-react"; + +export function LiveShareLoader({ children }) { + const { joined, joinError } = useLiveShareContext(); + + if (joinError) return <>{joinError.message}; + if (!joined) return <>Joining Live Share session...; + return <>{children} +} + +// LiveCheckbox.jsx +import { useLiveState } from "@microsoft/live-share-react"; + +export function LiveCheckbox() { + const [checked, setChecked] = useLiveState("MY-UNIQUE-ID", false); + return ( + { + setChecked(!checked); + }} + /> + ); +} + ``` */ export const useLiveShareContext = (): ILiveShareContext => { const context = React.useContext(LiveShareContext); @@ -103,9 +154,9 @@ export interface ILiveShareProviderProps { */ host: ILiveShareHost; /** - * The initial object schema to use when {@link joinOnLoad} is true. + * The schema to use when {@link joinOnLoad} is true. */ - initialObjects?: LoadableObjectClassRecord; + fluidContainerSchema?: ContainerSchema; /** * Optional. Flag to determine whether to join Fluid container on load. */ @@ -114,11 +165,62 @@ export interface ILiveShareProviderProps { /** * React Context provider component for using Live Share data objects & joining a Live Share session using `LiveShareClient`. + * + * @example + ```jsx +// LiveShareApp.jsx +import { LiveShareProvider } from "@microsoft/live-share-react"; +import { LiveShareHost } from "@microsoft/teams-js"; + +const host = LiveShareHost.create(); + +export function LiveShareApp() { + // Call app.initialize() from teams-js before rendering LiveShareProvider + + return ( + + + + + + ); +} + +// LiveShareLoader.jsx +import { useLiveShareContext } from "@microsoft/live-share-react"; + +export function LiveShareLoader({ children }) { + const { joined, joinError } = useLiveShareContext(); + + if (joinError) return <>{joinError.message}; + if (!joined) return <>Joining Live Share session...; + return <>{children} +} + +// LiveCheckbox.jsx +import { useLiveState } from "@microsoft/live-share-react"; + +export function LiveCheckbox() { + const [checked, setChecked] = useLiveState("MY-UNIQUE-ID", false); + return ( + { + setChecked(!checked); + }} + /> + ); +} + ``` */ export const LiveShareProvider: React.FC = (props) => { const startedRef = React.useRef(false); const clientRef = React.useRef( - new LiveShareTurboClient(props.host, props.clientOptions) + new LiveShareClient(props.host, props.clientOptions) ); const [results, setResults] = React.useState< ILiveShareJoinResults | undefined @@ -132,12 +234,12 @@ export const LiveShareProvider: React.FC = (props) => { */ const join = React.useCallback( async ( - initialObjects?: LoadableObjectClassRecord, + fluidContainerSchema?: ContainerSchema, onInitializeContainer?: (container: IFluidContainer) => void ): Promise => { startedRef.current = true; const results = await clientRef.current.join( - initialObjects, + fluidContainerSchema, onInitializeContainer ); setResults(results); @@ -155,7 +257,7 @@ export const LiveShareProvider: React.FC = (props) => { // We are not doing this here for backwards compatibility. View the README for more information. if (results !== undefined || startedRef.current || !props.joinOnLoad) return; - join(props.initialObjects).catch((error) => { + join(props.fluidContainerSchema).catch((error) => { console.error(error); if (error instanceof Error) { setJoinError(error); @@ -178,7 +280,7 @@ export const LiveShareProvider: React.FC = (props) => { ); } }); - }, [results, props.joinOnLoad, props.initialObjects, join]); + }, [results, props.joinOnLoad, props.fluidContainerSchema, join]); return ( { + [rawTNodeKey]: TNode; + [proxiedChildrenKey]: Record; +} + +export function isProxy(value: any): value is typeof Proxy { + return value && value["[[Handler]]"]; +} + +export function isCustomProxyHandler( + value: any +): value is ICustomProxyHandler { + return value?.[rawTNodeKey] !== undefined; +} + +export function isTreeNode(value: any): value is TreeNode { + try { + Tree.schema(value); + return true; + } catch (_) { + return false; + } +} diff --git a/packages/live-share-react/src/shared-hooks/internals/tree-node-utils.ts b/packages/live-share-react/src/shared-hooks/internals/tree-node-utils.ts new file mode 100644 index 000000000..ba7d98675 --- /dev/null +++ b/packages/live-share-react/src/shared-hooks/internals/tree-node-utils.ts @@ -0,0 +1,269 @@ +import { proxiedChildrenKey, rawTNodeKey } from "./tree-node-constants.js"; +import { + ICustomProxyHandler, + isCustomProxyHandler, + isTreeNode, + isProxy, +} from "./tree-node-types.js"; +import { TreeNode, Tree } from "fluid-framework"; +import { Dispatch, SetStateAction } from "react"; + +// Exported utils + +/** + * @internal + * Build a proxied version of a node and set its value to the treeMap provided + * + * @param rawNode the raw proxy node exposed by Fluid + * @param treeMap a map where Fluid's proxy node is mapped to our proxied node + * @returns TNode instance + */ +export function buildProxy( + rawNode: TNode, + treeMap: WeakMap +): TNode { + const previousProxy = treeMap.get(rawNode); + const previousProxyHandler = previousProxy + ? getCustomProxyHandler(previousProxy) + : undefined; + const proxyHandler: ProxyHandler & ICustomProxyHandler = { + // Add some extra stuff into the handler so we can store the original Fluid TreeNode and access it later + // Without overriding the rest of the getters in the object. + [rawTNodeKey]: rawNode, + [proxiedChildrenKey]: previousProxyHandler?.[proxiedChildrenKey] ?? {}, + get: (target, prop, _) => { + if (prop === "[[Handler]]") { + return proxyHandler; + } + if ( + typeof prop === "string" && + proxyHandler[proxiedChildrenKey][prop] + ) { + return proxyHandler[proxiedChildrenKey][prop]; + } + // pass in the rawNode so Fluid doesn't get confused by our proxy object and can find the flex node + const value = Reflect.get(target, prop, rawNode); + return typeof value === "function" && + typeof prop === "string" && + // TODO: need a better way of identifying which types of functions need to be proxied + // This is because if a developer uses an array prototype function, we need to return proxied + // objects so React can detect changes to those nodes... + !["map", "flatMap", "filter", "find", "indexOf"].includes(prop) + ? value.bind(rawNode) + : value; + }, + set(target, p, newValue, _) { + return Reflect.set(target, p, newValue, rawNode); + }, + }; + const proxy = new Proxy(rawNode, proxyHandler); + // Track the proxy for the rawNode + treeMap.set(rawNode, proxy); + // Set raw node getter so we can access it before things like Tree.on + return proxy as TNode; +} + +/** + * @internal + * Set up listeners for a given TreeNode. + * Will recursively call this function for all children nodes of each children until there are no more child nodes. + * + * @param parentRawNode raw parent node + * @param rootNodeForListener root node being listened to in useTreeNode + * @param treeMap a map where Fluid's proxy node is mapped to our proxied node + * @param unsubscribeListeners list of unsubscribe listeners, where we set the unsubscribe callbacks + * @param setProxyNode setter to set the root proxy node listened to in useTreeNode + */ +export function setUpListenersForNodeChildren< + TNode extends TreeNode = TreeNode, +>( + parentRawNode: TreeNode, + rootNodeForListener: TreeNode, + treeMap: WeakMap, + unsubscribeListeners: (() => void)[], + setProxyNode: Dispatch> +) { + let entries = Object.entries(parentRawNode); + for (let i = 0; i < entries.length; i++) { + const [key, entry] = entries[i]; + if ( + !entry || + ["string", "boolean", "number", "function"].includes( + typeof entry + ) || + !isTreeNode(entry) + ) { + continue; + } + const rawEntry = getRawNode(entry); + const onNodeChanged = () => { + onTreeNodeChanged( + key, + rawEntry, + rootNodeForListener, + treeMap, + setProxyNode + ); + }; + const unsubscribe = Tree.on(rawEntry, "nodeChanged", onNodeChanged); + unsubscribeListeners.push(unsubscribe); + // Recursively listen to children nodes of this node + setUpListenersForNodeChildren( + rawEntry, + rootNodeForListener, + treeMap, + unsubscribeListeners, + setProxyNode + ); + } +} + +/** + * @internal + * Fluid only knows how to work with their proxied version of a TreeNode. + * We store a reference to that node in our proxied instances so we can easily use it when working with Fluid APIs. + * + * @param node get the raw node from the proxy + * @returns the raw proxied node that Fluid expects + */ +export function getRawNode( + node: TNode +): TNode { + if (isProxy(node)) { + return getRawNodeFromProxy(node) as TNode; + } + return node; +} + +// Non public utils + +/** + * Callback for when a tree node changed + * + * @param key key where the object is stored in the parent + * @param rawNode the raw node that changed + * @param rootNodeForListener the root node that is being listened to in useTreeNode + * @param treeMap a map where Fluid's proxy node is mapped to our proxied node + * @param setProxyNode setter to set the root proxy node listened to in useTreeNode + */ +function onTreeNodeChanged( + key: string, + rawNode: TreeNode, + rootNodeForListener: TreeNode, + treeMap: WeakMap, + setProxyNode: Dispatch> +) { + const proxyNode = buildProxy(rawNode, treeMap); + const parent = Tree.parent(rawNode); + if (!parent) { + throw new Error( + "useTreeNode onTreeNodeChanged: no parent found for rawParentNode" + ); + } + + proxyParentForNode( + key, + parent, + proxyNode, + rootNodeForListener, + treeMap, + setProxyNode + ); +} + +/** + * Proxies the parent and sets reference to the child node that changed. + * + * @param key key where the object is referenced in its parent node + * @param rawParentNode raw parent tree node + * @param proxyNode proxied instance of the node that changed + * @param rootNodeForListener root node listened to in useTreeNode + * @param treeMap a map where Fluid's proxy node is mapped to our proxied node + * @param setProxyNode setter to set the root proxy node listened to in useTreeNode + */ +function proxyParentForNode( + key: string, + rawParentNode: TreeNode, + proxyNode: TreeNode, + rootNodeForListener: TreeNode, + treeMap: WeakMap, + setProxyNode: Dispatch> +) { + const parentProxy = buildProxy(rawParentNode, treeMap); + let parentProxyHandler = getCustomProxyHandler(parentProxy); + if (!parentProxyHandler) { + throw new Error( + "useTreeNode proxyParentForNode: unexpected error, should always find valid proxy handler" + ); + } + parentProxyHandler[proxiedChildrenKey][key] = proxyNode; + if (rawParentNode === rootNodeForListener) { + setProxyNode(parentProxy as TNode); + } else { + const parentOfParent = Tree.parent(rawParentNode); + if (!parentOfParent) { + throw new Error( + "useTreeNode proxyParentForNode: no parent found for rawParentNode" + ); + } + const parentKey = findKeyOfNode(rawParentNode, parentOfParent); + proxyParentForNode( + parentKey, + parentOfParent, + parentProxy, + rootNodeForListener, + treeMap, + setProxyNode + ); + } +} + +/** + * Returns key where parent[key] == nodeToCheck + * + * @param nodeToCheck tree node to check + * @param parent parent node where nodeToCheck is a child of + * @returns the key for node + */ +function findKeyOfNode(nodeToCheck: TreeNode, parent: TreeNode): string { + let entries = Object.entries(parent); + for (let i = 0; i < entries.length; i++) { + const [key, entry] = entries[i]; + if ( + !entry || + ["string", "boolean", "number", "function"].includes( + typeof entry + ) || + !isTreeNode(entry) + ) { + continue; + } + if (entry === nodeToCheck) return key; + } + throw new Error("Did not find node as a child of parent"); +} + +// Type utils + +/** + * Gets the proxy handler for a given TreeNode, assuming `isCustomProxyHandler` returns true. + * @param proxy the proxied TreeNode to get the handler for. + * @returns the handler if valid, otherwise undefined + */ +function getCustomProxyHandler(proxy: TreeNode) { + const handler = (proxy as any)["[[Handler]]"]; + if (isCustomProxyHandler(handler)) { + return handler; + } + return undefined; +} + +/** + * Gets the raw node for a given proxied tree node + * + * @param proxy the proxied TreeNode to get the raw node for + * @returns the raw node if valid, otherwise undefined + */ +function getRawNodeFromProxy(proxy: TreeNode) { + return getCustomProxyHandler(proxy)?.[rawTNodeKey]; +} diff --git a/packages/live-share-react/src/shared-hooks/useDynamicDDS.ts b/packages/live-share-react/src/shared-hooks/useDynamicDDS.ts index e4266844d..1446a6825 100644 --- a/packages/live-share-react/src/shared-hooks/useDynamicDDS.ts +++ b/packages/live-share-react/src/shared-hooks/useDynamicDDS.ts @@ -5,8 +5,8 @@ import React from "react"; import { FluidObject, IFluidLoadable } from "@fluidframework/core-interfaces"; -import { useFluidObjectsContext } from "../providers"; -import { LoadableObjectClass } from "fluid-framework"; +import { useFluidObjectsContext } from "../providers/AzureProvider.js"; +import { SharedObjectKind } from "fluid-framework"; /** * Hook to gets or creates a DDS that corresponds to a given uniqueKey string. @@ -14,17 +14,17 @@ import { LoadableObjectClass } from "fluid-framework"; * @remarks * This hook can only be used in a child component of `` or ``. * - * @template T Type of Fluid LoadableObjectClass type to load. Must conform to IFluidLoadable interface. + * @template T Type of Fluid SharedObjectKind type to load. Must conform to IFluidLoadable interface. * @param uniqueKey uniqueKey value for the data object - * @param loadableObjectClass Fluid LoadableObjectClass to create/load. + * @param objectKind Fluid SharedObjectKind to create/load. * @param onFirstInitialize Optional. Callback function for when the DDS is first loaded * @returns the DDS object, which is of type T when loaded and undefined while loading */ export function useDynamicDDS< - T extends IFluidLoadable = FluidObject & IFluidLoadable + T extends IFluidLoadable = FluidObject & IFluidLoadable, >( uniqueKey: string, - loadableObjectClass: LoadableObjectClass, + objectClass: SharedObjectKind, onFirstInitialize?: (dds: T) => void ): { dds: T | undefined; @@ -37,24 +37,38 @@ export function useDynamicDDS< */ const { container, clientRef } = useFluidObjectsContext(); + const mountedRef = React.useRef(false); + React.useEffect(() => { + mountedRef.current = true; + return () => { + mountedRef.current = false; + }; + }, []); + + const getDDSPromisesRef = React.useRef>>(new Map()); + /** * Once container is available, this effect will register the setter method so that the DDS loaded * from `dynamicObjects` that matches `uniqueKey` can be passed back to this hook. If one does not yet exist, * a new DDS is automatically created. If multiple users try to create a DDS at the same time when this component first - * mounts, `live-share-turbo` ensures it will ultimately self correct using last-writer wins. + * mounts, `live-share` ensures it will ultimately self correct using last-writer wins. */ React.useEffect(() => { if (container === undefined) return; - let mounted = true; // Callback method to set the `initialData` into the map when the DDS is first created. const onGetDDS = async () => { try { - const dds = await clientRef.current.getDDS( - uniqueKey, - loadableObjectClass, - onFirstInitialize - ); - if (mounted) { + let getPromise = getDDSPromisesRef.current.get(uniqueKey); + if (!getPromise) { + getPromise = clientRef.current.getDDS( + uniqueKey, + objectClass, + onFirstInitialize + ); + getDDSPromisesRef.current.set(uniqueKey, getPromise); + } + const dds = await getPromise; + if (mountedRef.current) { setDDS(dds); } } catch (error: unknown) { @@ -70,9 +84,6 @@ export function useDynamicDDS< } }; onGetDDS(); - return () => { - mounted = false; - }; }, [container, uniqueKey, onFirstInitialize]); return { diff --git a/packages/live-share-react/src/shared-hooks/useSharedMap.ts b/packages/live-share-react/src/shared-hooks/useSharedMap.ts index e8ff7d359..1f411cfba 100644 --- a/packages/live-share-react/src/shared-hooks/useSharedMap.ts +++ b/packages/live-share-react/src/shared-hooks/useSharedMap.ts @@ -4,17 +4,20 @@ */ import React from "react"; -import { isEntries, isJSON, isMap } from "../utils"; -import { IUseSharedMapResults, SharedMapInitialData } from "../types"; -import { useDynamicDDS } from "./useDynamicDDS"; -import { SharedMap } from "fluid-framework"; -import { useFluidObjectsContext } from "../providers"; +import { isEntries, isJSON, isMap } from "../utils/index.js"; +import { IUseSharedMapResults, SharedMapInitialData } from "../types/index.js"; +import { useDynamicDDS } from "./useDynamicDDS.js"; +import { SharedMap } from "fluid-framework/legacy"; import { ActionContainerNotJoinedError, ActionLiveDataObjectUndefinedError, -} from "../internal"; +} from "../internal/errors.js"; +import { useFluidObjectsContext } from "../providers/AzureProvider.js"; +import { useSharedTree } from "./useSharedTree.js"; /** + * @deprecated use {@link useSharedTree} instead. + * * React hook for using a Fluid `SharedMap`. * * @remarks @@ -28,19 +31,12 @@ import { * will be created, otherwise it will use the existing one. * @param initialData a JS Map, entries array, or JSON object to insert into the `SharedMap` when creating * the DDS for the first time. - * @returns stateful `map` entries, `setEntry` callback, `deleteEntry` callback, and the Fluid `sharedMap`. + * @returns the Fluid `sharedMap`. */ export function useSharedMap( uniqueKey: string, initialData?: SharedMapInitialData ): IUseSharedMapResults { - /** - * Stateful readonly map (user facing) with most recent values from `SharedMap` and its setter method. - */ - const [map, setMap] = React.useState>( - getInitialData(initialData) - ); - const onFirstInitialize = React.useCallback( (newDDS: SharedMap): void => { /** @@ -64,6 +60,28 @@ export function useSharedMap( const { container } = useFluidObjectsContext(); + /** + * User facing: get a value from the Fluid `SharedMap`. + */ + const getEntry = React.useCallback( + (key: string) => { + if (!container) { + throw new ActionContainerNotJoinedError( + "sharedMap", + "getEntry" + ); + } + if (sharedMap === undefined) { + throw new ActionLiveDataObjectUndefinedError( + "sharedMap", + "getEntry" + ); + } + return sharedMap.get(key); + }, + [container, sharedMap] + ); + /** * User facing: set a value to the Fluid `SharedMap`. */ @@ -108,13 +126,20 @@ export function useSharedMap( [container, sharedMap] ); + const [sharedMapProxy, setSharedMapProxy] = React.useState(); + // Setup change listeners, initial values, etc. React.useEffect(() => { if (!sharedMap) return; + setSharedMapProxy(sharedMap); + + class SharedMapProxyHandler implements ProxyHandler {} // Register valueChanged listener for `SharedMap`. const onValueChanged = () => { - setMap(new Map(sharedMap.entries())); + setSharedMapProxy( + new Proxy(sharedMap, new SharedMapProxyHandler()) + ); }; sharedMap.on("valueChanged", onValueChanged); // Get initial values from `SharedMap`. @@ -127,10 +152,10 @@ export function useSharedMap( }, [sharedMap]); return { - map, + sharedMap: sharedMapProxy, + getEntry, setEntry, deleteEntry, - sharedMap, }; } diff --git a/packages/live-share-react/src/shared-hooks/useSharedState.ts b/packages/live-share-react/src/shared-hooks/useSharedState.ts index 071cd7ce5..0172fb8a3 100644 --- a/packages/live-share-react/src/shared-hooks/useSharedState.ts +++ b/packages/live-share-react/src/shared-hooks/useSharedState.ts @@ -4,10 +4,13 @@ */ import React from "react"; -import { useFluidObjectsContext } from "../providers"; -import { DisposeSharedStateAction, SetSharedStateAction } from "../types"; +import { useFluidObjectsContext } from "../providers/index.js"; +import { + DisposeSharedStateAction, + SetSharedStateAction, +} from "../types/index.js"; import { v4 as uuid } from "uuid"; -import { isPrevStateCallback } from "../internal"; +import { isPrevStateCallback } from "../internal/index.js"; /** * Inspired by React's `useState` hook, `useSharedState` makes it easy to synchronize state in your app. diff --git a/packages/live-share-react/src/shared-hooks/useSharedStateRegistry.ts b/packages/live-share-react/src/shared-hooks/useSharedStateRegistry.ts index 9ede09b6e..a11019bd5 100644 --- a/packages/live-share-react/src/shared-hooks/useSharedStateRegistry.ts +++ b/packages/live-share-react/src/shared-hooks/useSharedStateRegistry.ts @@ -3,7 +3,11 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { IValueChanged, SharedMap } from "fluid-framework"; +import { + IFluidContainer, + IValueChanged, + SharedMap, +} from "fluid-framework/legacy"; import React from "react"; import { DeleteSharedStateAction, @@ -12,7 +16,13 @@ import { SetLocalStateAction, UnregisterSharedSetStateAction, UpdateSharedStateAction, -} from "../types"; +} from "../types/index.js"; +import { + getRootDataObject, + getRootDirectory, + TurboDirectory, + TurboStateMap, +} from "@microsoft/live-share/internal"; /** * Response for the {@link useSharedStateRegistry} hook. @@ -52,6 +62,8 @@ export const useSharedStateRegistry = ( Map> >(new Map()); + const stateMap = useStateMap(results?.container); + /** * @see ISharedStateRegistryResponse.registerSharedSetStateAction */ @@ -76,14 +88,12 @@ export const useSharedStateRegistry = ( ); } // Set initial values, if known - const stateMap = results?.container.initialObjects - .TURBO_STATE_MAP as SharedMap | undefined; const initialValue = stateMap?.get(uniqueKey); if (initialValue) { setLocalStateAction(initialValue); } }, - [results] + [stateMap] ); /** @@ -105,13 +115,10 @@ export const useSharedStateRegistry = ( */ const updateSharedState: UpdateSharedStateAction = React.useCallback( (uniqueKey: string, value: any) => { - if (!results) return; - const { container } = results; - const stateMap = container.initialObjects - .TURBO_STATE_MAP as SharedMap; - stateMap.set(uniqueKey, value); + if (!stateMap) return; + stateMap?.set(uniqueKey, value); }, - [results] + [stateMap] ); /** @@ -119,25 +126,20 @@ export const useSharedStateRegistry = ( */ const deleteSharedState: DeleteSharedStateAction = React.useCallback( (uniqueKey: string) => { - if (!results) return; - const { container } = results; + if (!stateMap) return; let actionsMap = registeredSharedSetStateActionMapRef.current.get(uniqueKey); actionsMap?.clear(); - const stateMap = container.initialObjects - .TURBO_STATE_MAP as SharedMap; stateMap.delete(uniqueKey); }, - [results] + [stateMap] ); React.useEffect(() => { - if (!results) return; - const { container } = results; - const stateMap = container.initialObjects.TURBO_STATE_MAP as SharedMap; + if (!stateMap) return; const valueChangedListener = (changed: IValueChanged): void => { if (registeredSharedSetStateActionMapRef.current.has(changed.key)) { - const value = stateMap.get(changed.key); + const value = stateMap?.get(changed.key); const actionMap = registeredSharedSetStateActionMapRef.current.get( changed.key @@ -157,9 +159,9 @@ export const useSharedStateRegistry = ( }); }); return () => { - stateMap.off("valueChanged", valueChangedListener); + stateMap?.off("valueChanged", valueChangedListener); }; - }, [results]); + }, [stateMap]); return { registerSharedSetStateAction, @@ -168,3 +170,23 @@ export const useSharedStateRegistry = ( deleteSharedState, }; }; + +const useStateMap = (container: IFluidContainer | undefined) => { + const [stateMap, setStateMap] = React.useState(); + React.useEffect(() => { + if (!container) { + return; + } + const rootDataObject = getRootDataObject(container); + const rootDirectory = getRootDirectory(rootDataObject); + const turboDir = rootDirectory.getSubDirectory(TurboDirectory); + turboDir + ?.get(TurboStateMap) + .get() + .then((state: SharedMap) => { + setStateMap(state); + }); + }, [container]); + + return stateMap; +}; diff --git a/packages/live-share-react/src/shared-hooks/useSharedTree.ts b/packages/live-share-react/src/shared-hooks/useSharedTree.ts new file mode 100644 index 000000000..6b43eba91 --- /dev/null +++ b/packages/live-share-react/src/shared-hooks/useSharedTree.ts @@ -0,0 +1,144 @@ +import { + ImplicitFieldSchema, + TreeViewConfiguration, + SharedTree, + TreeView, + ITree, + InsertableTreeFieldFromImplicitField, + TreeFieldFromImplicitField, +} from "fluid-framework"; +import { IUseSharedTreeResults } from "../types/index.js"; +import { useDynamicDDS, useTreeNode } from "../shared-hooks/index.js"; +import React from "react"; + +/** + * Creates a new Fluid `SharedTree` instance if one doesn't already exist. + * @remarks + * Use the `root` variable from the {@link IUseSharedTreeResults} response from this hook with {@link useTreeNode}. + * This makes `root` stateful with React whenever a leaf of `root` changes. + * + * @param uniqueKey the unique key for the `SharedTree`. If one does not yet exist, a new `SharedTree` will be created. + * Otherwise it will use the existing one. + * @param treeViewConfiguration the tree view configuration that contains the `SharedTree` field schema. + * @param initialData the initial data to load into the `SharedTree` when it is first created. + * @returns the {@link IUseSharedTreeResults} with the `root` node. + * + * @example + * ```tsx + * import { SchemaFactory, TreeViewConfiguration } from "fluid-framework"; + * import { useSharedTree, useTreeNode } from "@microsoft/live-share-react"; + * // Declare a schema factory with your unique uuid + * const sf = new SchemaFactory("fc1db2e8-0000-11ee-be57-0242ac120002"); + * class YourObject extends sf.object("YourObject", { + * listChangedCount: sf.number, + * list: sf.array(sf.string), + * }) { + * // You can add your own utility functions + * insert() { + * this.list.insertAtEnd("some text"); + * this.listChangedCount += 1; + * } + * } + * const config = new TreeViewConfiguration({ schema: YourObject }); + * const initialData = new YourObject({ + * number: 0, + * list: [], + * }); + * + * // Must be child component of or + * export const YourComponent = () => { + * // Get the root node of the `SharedTree` mapped to "some-unique-key" + * const { root } = useSharedTree("some-unique-key", config, initialData); + * // Makes root stateful / automatically update when the node changes (e.g., node.count) + * const { node } = useTreeNode(root); + * // node.list is its own TreeNode, so we make it stateful as well + * const { node: list } = useTreeNode(node?.list); + * if (!node || !list) return (<>"Loading"); + * return ( + *
        + *
        Changed: {node.listChangedCount}
        + * + * { list.map((item) =>
        {item}
        ) } + *
        + * ); + * } + * ``` + */ +export function useSharedTree< + TSchema extends ImplicitFieldSchema = ImplicitFieldSchema, +>( + uniqueKey: string, + treeViewConfiguration: TreeViewConfiguration, + initialData: InsertableTreeFieldFromImplicitField +): IUseSharedTreeResults { + const [treeView, setTreeView] = React.useState>(); + const [root, setRoot] = + React.useState>(); + + const onFirstInitialize = React.useCallback( + (newDDS: ITree): void => { + try { + // Create a `treeView` with the provided `treeViewConfiguration` + const _treeView = newDDS.viewWith(treeViewConfiguration); + if (_treeView.compatibility.canInitialize) { + // Set initial data + _treeView.initialize(initialData); + } + // `onFirstInitialize` is only called for the user that created the tree, but we need this object for all clients. + // Dispose, since we will call `sharedTree.viewWith` in a `useEffect` down below and set it to state. + _treeView.dispose(); + } catch (err) { + console.error(err); + } + }, + [treeViewConfiguration, initialData] + ); + /** + * User facing: dynamically load the `SharedTree` DDS for the given unique key. + */ + const { dds: sharedTree } = useDynamicDDS( + uniqueKey, + SharedTree, + onFirstInitialize + ); + + /** + * Sets the tree view and root view + */ + React.useEffect(() => { + if (!sharedTree) return; + let _treeView: TreeView | undefined = undefined; + try { + // Create a `treeView` with the provided `treeViewConfiguration` + _treeView = sharedTree.viewWith(treeViewConfiguration); + setTreeView(_treeView); + } catch (err) { + console.error(err); + } + + // Listen for changes to root view + const updateRoot = (): void => { + if (_treeView?.compatibility.canView) { + setRoot(_treeView.root); + } else { + setRoot(undefined); + } + }; + + updateRoot(); + const unsubscribeToRoot = _treeView?.events.on( + "rootChanged", + updateRoot + ); + return () => { + _treeView?.dispose(); + unsubscribeToRoot?.(); + }; + }, [sharedTree, treeViewConfiguration]); + + return { + treeView, + sharedTree, + root, + }; +} diff --git a/packages/live-share-react/src/shared-hooks/useTreeNode.ts b/packages/live-share-react/src/shared-hooks/useTreeNode.ts new file mode 100644 index 000000000..ef98ea9a4 --- /dev/null +++ b/packages/live-share-react/src/shared-hooks/useTreeNode.ts @@ -0,0 +1,147 @@ +import { Tree, TreeChangeEvents, TreeNode } from "fluid-framework"; +import { IUseTreeNodeResults } from "../types/index.js"; +import { useEffect, useRef, useState } from "react"; +import { + getRawNode, + buildProxy, + setUpListenersForNodeChildren, +} from "./internals/tree-node-utils.js"; + +/** + * Makes a provided Fluid `TreeNode` stateful in React. + * + * @param node the Fluid `SharedTree` `TreeNode` instance to make stateful. + * @param stateChangeType listener type to apply changes for. Default value is "nodeChanged", which has the most optimal performance. + * Provide "treeChanged" to make all children nodes stateful as well when those child nodes change. + * When using the default, you must pass all child `TreeNode` values into `useTreeNode` for them to be stateful as well. + * @returns a stateful version `node` + * + * @example + * Example using default `"nodeChanged"` `stateChangeType` + * ```tsx + * import { SchemaFactory, TreeViewConfiguration } from "fluid-framework"; + * import { useSharedTree, useTreeNode } from "@microsoft/live-share-react"; + * // Declare a schema factory with your unique uuid + * const sf = new SchemaFactory("fc1db2e8-0000-11ee-be57-0242ac120002"); + * class YourObject extends sf.object("YourObject", { + * listChangedCount: sf.number, + * list: sf.array(sf.string), + * }) { + * // You can add your own utility functions + * insert() { + * this.list.insertAtEnd("some text"); + * this.listChangedCount += 1; + * } + * } + * const config = new TreeViewConfiguration({ schema: YourObject }); + * const initialData = new YourObject({ + * number: 0, + * list: [], + * }); + * + * // Must be child component of or + * export const YourComponent = () => { + * // Get the root node of the `SharedTree` mapped to "some-unique-key" + * const { root } = useSharedTree("some-unique-key", config, initialData); + * // Makes root stateful / automatically update when the node changes (e.g., node.count) + * const { node } = useTreeNode(root); + * // node.list is its own TreeNode, so we make it stateful as well + * const { node: list } = useTreeNode(node?.list); + * if (!node || !list) return (<>"Loading"); + * return ( + *
        + *
        Changed: {node.listChangedCount}
        + * + * { list.map((item) =>
        {item}
        ) } + *
        + * ); + * } + * ``` + * + * @example + * Example using `"treeChanged"` `stateChangeType` + * ```tsx + * import { SchemaFactory, TreeViewConfiguration } from "fluid-framework"; + * import { useSharedTree, useTreeNode } from "@microsoft/live-share-react"; + * // Declare a schema factory with your unique uuid + * const sf = new SchemaFactory("fc1db2e8-0000-11ee-be57-0242ac120002"); + * + * class ChildObject extends sf.object("ChildObject", { + * count: sf.number, + * }) { + * increment() { + * this.count += 1; + * } + * } + * + * class YourObject extends sf.object("YourObject", { + * child: ChildObject, + * }) {} + * const config = new TreeViewConfiguration({ schema: YourObject }); + * const initialData = new YourObject({ + * child: new ChildObject({ count: 0 }), + * }); + * + * // Must be child component of or + * export const YourComponent = () => { + * // Get the root node of the `SharedTree` mapped to "some-unique-key" + * const { root } = useSharedTree("some-unique-key", config, initialData); + * // Using "treeChanged" prop makes all children nodes stateful as well. + * // Use with caution / measure render performance with React dev tools. + * const { node } = useTreeNode(root, "treeChanged"); + * if (!node) return (<>"Loading"); + * return ( + *
        + *
        Changed: {node.child.count}
        + * + *
        + * ); + * } + * ``` + */ +export function useTreeNode( + node: TNode, + stateChangeType: keyof TreeChangeEvents = "nodeChanged" +): IUseTreeNodeResults { + // When we return a proxied node to a developer, it's possible they will pass it back to us in this hook. + // We can't listen using Tree.on using a proxy node though... + // Thus, if we are already listening to a node from another instance of this hook, we look for the unproxied node. + const rawNode = getRawNode(node); + const [proxyNode, setProxyNode] = useState(rawNode); + const treeProxyMapRef = useRef>(new WeakMap()); + + useEffect(() => { + if (!rawNode) return; + + // Set default value + setProxyNode(rawNode); + function onNodeChanged() { + if (!rawNode) return; + + const proxyNode = buildProxy(rawNode, treeProxyMapRef.current); + setProxyNode(proxyNode); + } + // Listen to Fluid's base node from their TreeView so Fluid flex nodes continue to work + const unsubscribeListeners: (() => void)[] = [ + Tree.on(rawNode, "nodeChanged", onNodeChanged), + ]; + if (stateChangeType === "treeChanged") { + // Recursively for all child nodes of this node in the tree + setUpListenersForNodeChildren( + rawNode, + rawNode, + treeProxyMapRef.current, + unsubscribeListeners, + // TODO: fix typing so casting isn't necessary + setProxyNode as any + ); + } + return () => { + unsubscribeListeners.forEach((unsubscribe) => unsubscribe()); + }; + }, [rawNode, stateChangeType]); + + return { + node: proxyNode, + }; +} diff --git a/packages/live-share-react/src/types/ActionTypes.ts b/packages/live-share-react/src/types/ActionTypes.ts index d3bf6451c..ee0e6f2ba 100644 --- a/packages/live-share-react/src/types/ActionTypes.ts +++ b/packages/live-share-react/src/types/ActionTypes.ts @@ -5,8 +5,12 @@ import React from "react"; import { IFluidLoadable } from "@fluidframework/core-interfaces"; -import { LoadableObjectClass } from "fluid-framework"; -import { ITimerConfig, ILiveEvent, PresenceState } from "@microsoft/live-share"; +import { + ITimerConfig, + ILiveEvent, + LivePresenceData, +} from "@microsoft/live-share"; +import { SharedObjectKind } from "fluid-framework"; // React actions @@ -25,12 +29,12 @@ export type SetLocalStateAction = React.Dispatch>; /** * Callback for UnregisterDDSSetStateAction. - * (uniqueKey: string, componentId: string, objectClass: LoadableObjectClass, setLocalStateAction: SetLocalStateAction, onDidFirstInitialize?: (dds: T) => void) => void + * (uniqueKey: string, componentId: string, objectClass: SharedObjectKind, setLocalStateAction: SetLocalStateAction, onDidFirstInitialize?: (dds: T) => void) => void */ export type RegisterDDSSetStateAction = ( uniqueKey: string, componentId: string, - objectClass: LoadableObjectClass, + objectClass: SharedObjectKind, setLocalStateAction: SetLocalStateAction, onDidFirstInitialize?: (dds: T) => void ) => void; @@ -92,10 +96,11 @@ export type SetLiveStateAction = ( /** * Callback for SendLiveEventAction. - * (event: TEvent) => Promise + * (event: TEvent, targetClientId?: string) => Promise */ export type SendLiveEventAction = ( - event: TEvent + event: TEvent, + targetClientId?: string ) => Promise>; /** @@ -111,9 +116,8 @@ export type OnReceivedLiveEventAction = ( * Callback for OnUpdateLivePresenceAction. * (data?: TData | undefined, state?: PresenceState | undefined) => Promise */ -export type OnUpdateLivePresenceAction = ( - data?: TData | undefined, - state?: PresenceState | undefined +export type OnUpdateLivePresenceAction = ( + data: TData ) => Promise; /** diff --git a/packages/live-share-react/src/types/PropTypes.ts b/packages/live-share-react/src/types/PropTypes.ts index 10ff768e4..bcf342acd 100644 --- a/packages/live-share-react/src/types/PropTypes.ts +++ b/packages/live-share-react/src/types/PropTypes.ts @@ -3,8 +3,65 @@ * Licensed under the Microsoft Live Share SDK License. */ +import { UserMeetingRole } from "@microsoft/live-share"; +import { + CanvasReferencePoint, + IBrush, + IPoint, + InkingTool, + LiveCanvasTreeNode, +} from "@microsoft/live-share-canvas"; +import { useLiveCanvas } from "../live-hooks/index.js"; + export type SharedMapInitialData = | Map | readonly (readonly [string, T])[] | { [key: string]: T } | undefined; + +/** + * Optional props for {@link useLiveCanvas} + */ +export interface IUseLiveCanvasOptionalProps { + /** + * Optional. Stateful boolean that will activate/de-activate `InkingManager` accordingly. + */ + active?: boolean; + /** + * Optional. Stateful enum for what tool to use in the `InkingManager`. + */ + tool?: InkingTool; + /** + * Optional. Stateful lineBrush object for the selected lineBrush options to use in `InkingManager`. + */ + lineBrush?: IBrush; + /** + * Optional. Stateful offset point to use in the `InkingManager`. Gets the viewport offset. Defaults to 0,0. + */ + offset?: IPoint; + /** + * Optional. Stateful scale number to use in the `InkingManager`. Defaults to 1 and must be greater than 0. + */ + scale?: number; + /** + * Optional. Stateful reference point enum to use in the `InkingManger`. Defaults to "center". + */ + referencePoint?: CanvasReferencePoint; + /** + * Optional. Stateful boolean flag for whether cursor should be shared in `LiveCanvas`. Defaults to false. + */ + isCursorShared?: boolean; + /** + * Optional. url string for the local user to display alongside their cursor. Defaults to undefined. + */ + localUserPictureUrl?: string; + /** + * Optional. A Fluid `LiveCanvasTree` `TreeNode` instance to swap out the underlying storage solution for strokes. + * To learn more, look at Fluid's [SharedTree](https://fluidframework.com/docs/data-structures/tree/) documentation. + */ + node?: LiveCanvasTreeNode; + /** + * Optional. The user roles that are allowed to start/stop/pause the timer. + */ + allowedRoles?: UserMeetingRole[]; +} diff --git a/packages/live-share-react/src/types/ResultTypes.ts b/packages/live-share-react/src/types/ResultTypes.ts index 9ea12a283..a37029220 100644 --- a/packages/live-share-react/src/types/ResultTypes.ts +++ b/packages/live-share-react/src/types/ResultTypes.ts @@ -13,6 +13,7 @@ import { IFollowModeState, FollowModePresenceUser, LiveFollowMode, + LivePresenceData, } from "@microsoft/live-share"; import { InkingManager, LiveCanvas } from "@microsoft/live-share-canvas"; import { @@ -20,15 +21,35 @@ import { ExtendedMediaMetadata, MediaPlayerSynchronizer, } from "@microsoft/live-share-media"; -import { IFluidContainer, SharedMap } from "fluid-framework"; -import { IReceiveLiveEvent } from "../interfaces"; +import { + IFluidContainer, + ITree, + ImplicitFieldSchema, + TreeFieldFromImplicitField, + TreeView, +} from "fluid-framework"; +import { SharedMap } from "fluid-framework/legacy"; +import { + useSharedMap, + useTreeNode, + useSharedTree, +} from "../shared-hooks/index.js"; +import { + useLiveEvent, + useLivePresence, + useMediaSynchronizer, + useLiveTimer, + useLiveCanvas, + useLiveFollowMode, +} from "../live-hooks/index.js"; +import { IReceiveLiveEvent } from "../interfaces/index.js"; import { OnPauseTimerAction, OnPlayTimerAction, OnStartTimerAction, OnUpdateLivePresenceAction, SendLiveEventAction, -} from "./ActionTypes"; +} from "./ActionTypes.js"; export interface IAzureContainerResults { /** @@ -49,13 +70,19 @@ export interface ILiveShareContainerResults extends IAzureContainerResults { } /** - * Return type of `useSharedMap` hook. + * @deprecated use {@link useSharedTree} instead. + * + * Return type of {@link useSharedMap} hook. */ export interface IUseSharedMapResults { /** - * Stateful map of most recent values from `SharedMap`. + * The Fluid `SharedMap` object. */ - map: ReadonlyMap; + sharedMap: (Map & SharedMap) | undefined; + /** + * Callback method to get entries in the `SharedMap`. + */ + getEntry: (key: string) => TData | undefined; /** * Callback method to set/replace new entries in the `SharedMap`. */ @@ -64,14 +91,38 @@ export interface IUseSharedMapResults { * Callback method to delete an existing entry in the `SharedMap`. */ deleteEntry: (key: string) => void; +} + +/** + * Return type of {@link useSharedTree} hook. + */ +export interface IUseSharedTreeResults { + /** + * The Fluid `TreeView`. + */ + treeView: TreeView | undefined; /** - * The Fluid `SharedMap` object, should you want to use it directly. + * The Fluid `SharedTree` object, should you want to use it directly. */ - sharedMap: SharedMap | undefined; + sharedTree: ITree | undefined; + /** + * Root node + */ + root: TreeFieldFromImplicitField | undefined; +} + +/** + * Return type of {@link useTreeNode} hook. + */ +export interface IUseTreeNodeResults { + /** + * The Fluid `TreeNode` + */ + node: TNode; } /** - * Return type of `useLiveEvent` hook. + * Return type of {@link useLiveEvent} hook. */ export interface IUseLiveEventResults { /** @@ -95,7 +146,7 @@ export interface IUseLiveEventResults { } /** - * Return type of `useLiveTimer` hook. + * Return type of {@link useLiveTimer} hook. */ export interface IUseLiveTimerResults { /** @@ -129,9 +180,9 @@ export interface IUseLiveTimerResults { } /** - * Return type of `useLivePresence` hook. + * Return type of {@link useLivePresence} hook. */ -export interface IUseLivePresenceResults { +export interface IUseLivePresenceResults { /** * The local user's presence object. */ @@ -140,6 +191,10 @@ export interface IUseLivePresenceResults { * List of non-local user's presence objects. */ otherUsers: LivePresenceUser[]; + /** + * List of all online users. + */ + onlineUsers: LivePresenceUser[]; /** * List of all user's presence objects. */ @@ -150,15 +205,14 @@ export interface IUseLivePresenceResults { livePresence: LivePresence | undefined; /** * Callback method to update the local user's presence. - * @param data Optional. TData to set for user. - * @param state Optional. PresenceState to set for user. + * @param data TData to set for user. * @returns void promise that will throw when user does not have required roles */ updatePresence: OnUpdateLivePresenceAction; } /** - * Return type of `useMediaSynchronizer` hook. + * Return type of {@link useMediaSynchronizer} hook. */ export interface IUseMediaSynchronizerResults { /** @@ -208,7 +262,7 @@ export interface IUseMediaSynchronizerResults { } /** - * Return type of `useLiveCanvas` hook. + * Return type of {@link useLiveCanvas} hook. */ export interface IUseLiveCanvasResults { /** @@ -222,7 +276,7 @@ export interface IUseLiveCanvasResults { } /** - * Return type of `useLiveFollowMode` hook. + * Return type of {@link useLiveFollowMode} hook. */ export interface IUseLiveFollowModeResults { /** diff --git a/packages/live-share-react/src/types/index.ts b/packages/live-share-react/src/types/index.ts index 4805d6d32..c9e3eaf79 100644 --- a/packages/live-share-react/src/types/index.ts +++ b/packages/live-share-react/src/types/index.ts @@ -1,3 +1,3 @@ -export * from "./ActionTypes"; -export * from "./ResultTypes"; -export * from "./PropTypes"; +export * from "./ActionTypes.js"; +export * from "./ResultTypes.js"; +export * from "./PropTypes.js"; diff --git a/packages/live-share-react/src/utils/index.ts b/packages/live-share-react/src/utils/index.ts index c506df9be..349f0b61f 100644 --- a/packages/live-share-react/src/utils/index.ts +++ b/packages/live-share-react/src/utils/index.ts @@ -1 +1 @@ -export * from "./type-check"; +export * from "./type-check.js"; diff --git a/packages/live-share-react/tsconfig.build.json b/packages/live-share-react/tsconfig.build.json deleted file mode 100644 index 9f17e43fc..000000000 --- a/packages/live-share-react/tsconfig.build.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ - } - } \ No newline at end of file diff --git a/packages/live-share-react/tsconfig.json b/packages/live-share-react/tsconfig.json index 151892a6d..7fd77dccb 100644 --- a/packages/live-share-react/tsconfig.json +++ b/packages/live-share-react/tsconfig.json @@ -1,72 +1,66 @@ { - "compilerOptions": { - /* Visit https://aka.ms/tsconfig.json to read more about this file */ - - /* Basic Options */ - // "incremental": true, /* Enable incremental compilation */ - "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ - "module": "ES2020", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ - "lib": ["es2020","DOM", "DOM.Iterable"], /* Specify library files to be included in the compilation. */ - "allowJs": false, /* Allow javascript files to be compiled. */ - // "checkJs": true, /* Report errors in .js files. */ - "jsx": "react-jsx", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ - "declaration": true, /* Generates corresponding '.d.ts' file. */ - "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ - "sourceMap": true, /* Generates corresponding '.map' file. */ - // "outFile": "./", /* Concatenate and emit output to single file. */ - "outDir": "./bin", /* Redirect output structure to the directory. */ - // "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ - // "composite": true, /* Enable project compilation */ - // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ - // "removeComments": true, /* Do not emit comments to output. */ - // "noEmit": true, /* Do not emit outputs. */ - // "importHelpers": true, /* Import emit helpers from 'tslib'. */ - // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ - // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ - - /* Strict Type-Checking Options */ - "strict": true, /* Enable all strict type-checking options. */ - // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* Enable strict null checks. */ - // "strictFunctionTypes": true, /* Enable strict checking of function types. */ - // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ - // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ - // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ - // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ - - /* Additional Checks */ - // "noUnusedLocals": true, /* Report errors on unused locals. */ - // "noUnusedParameters": true, /* Report errors on unused parameters. */ - // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ - // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - - /* Module Resolution Options */ - "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ - // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ - // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ - // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ - // "typeRoots": [], /* List of folders to include type definitions from. */ - // "types": [], /* Type declaration files to be included in compilation. */ - // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ - "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ - // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - - /* Source Map Options */ - // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ - // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ - - /* Experimental Options */ - // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ - // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ - - /* Advanced Options */ - "skipLibCheck": true, /* Skip type checking of declaration files. */ - "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ - }, - "files": [ - "src/index.ts" - ] + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + /* Basic Options */ + // "incremental": true, /* Enable incremental compilation */ + "target": "ES2022" /* Specify ECMAScript target version. */, + "module": "Node16" /* Specify module code generation. */, + "lib": [ + "ES2022", + "DOM" + ] /* Specify library files to be included in the compilation. */, + "allowJs": false /* Allow javascript files to be compiled. */, + // "checkJs": true, /* Report errors in .js files. */ + "jsx": "react-jsx" /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */, + "declaration": true /* Generates corresponding '.d.ts' file. */, + "declarationMap": true /* Generates a sourcemap for each corresponding '.d.ts' file. */, + "sourceMap": true /* Generates corresponding '.map' file. */, + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "./bin/esm" /* Redirect output structure to the directory. */, + // "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + /* Strict Type-Checking Options */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + /* Module Resolution Options */ + // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + /* Advanced Options */ + "skipLibCheck": true /* Skip type checking of declaration files. */, + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + }, + "files": ["src/index.ts"] } diff --git a/packages/live-share-turbo/.nycrc.json b/packages/live-share-turbo/.nycrc.json deleted file mode 100644 index cc236d58b..000000000 --- a/packages/live-share-turbo/.nycrc.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "cache": false, - "extension": [".ts"], - "check-coverage": true, - "include": ["src/**"], - "exclude": ["src/pps/**"], - "statements": 90, - "branches": 90, - "functions": 95, - "lines": 90 - } \ No newline at end of file diff --git a/packages/live-share-turbo/LICENSE b/packages/live-share-turbo/LICENSE deleted file mode 100644 index 55955318b..000000000 --- a/packages/live-share-turbo/LICENSE +++ /dev/null @@ -1,87 +0,0 @@ -MICROSOFT SOFTWARE LICENSE TERMS - -MICROSOFT LIVE SHARE SDK – PRE-RELEASE VERSION -________________________________________ - -These license terms are an agreement between you and Microsoft Corporation (or one of its affiliates). They apply to the software named above and any Microsoft services or software updates (except to the extent such services or updates are accompanied by new or additional terms, in which case those different terms apply prospectively and do not alter your or Microsoft’s rights relating to pre-updated software or services). IF YOU COMPLY WITH THESE LICENSE TERMS, YOU HAVE THE RIGHTS BELOW. BY USING THE SOFTWARE, YOU ACCEPT THESE TERMS. - -1. INSTALLATION AND USE RIGHTS. - a) General. You may install and use any number of copies of the software to develop and test your applications, solely for the purpose stated in 1(b) below and otherwise for your internal business purposes. - b) Purpose. The use of this license provided under these terms is specifically limited to developing applications that interact solely within the Microsoft Teams Ecosystem. You may distribute the software according to Section 3 of these terms. - c) Third Party Components. The software may include third party components with separate legal notices or governed by other agreements, as may be described in the ThirdPartyNotices file(s) accompanying the software. - d) Microsoft Terms of Use. Some features of the software provide access to, or rely on, online services. The use of those services (but not the software) is governed by separate terms. This includes the Microsoft APIs Terms of Use which can be found at https://docs.microsoft.com/en-us/legal/microsoft-apis/terms-of-use and the Supplemental Terms of Use for Microsoft Azure which can be found at https://azure.microsoft.com/en-us/support/legal/preview-supplemental-terms. Please read them. The services may not be available in all regions. - -2. PRE-RELEASE SOFTWARE. The software is a pre-release version, and comes with no warranties as provided under Section 13. It may not operate correctly. We may change or discontinue the software at any time without notice. We may also choose not to make this software generally commercially available. It may be different from the commercially released version. - -3. DISTRIBUTABLE CODE. The software contains code you are permitted to distribute (i.e. make available for third parties) in applications you develop, as described in this Section. - a) Distribution Rights. The code and test files are distributable if included with the software. - i. Third Party Distribution. You may permit distributors of your applications to copy and distribute any of this distributable code you elect to distribute with your applications. - b) Distribution Requirements. For any code you distribute, you must: - i. adhere to the Purpose stated in Section 1(b); and - ii. indemnify, defend, and hold harmless Microsoft from any claims, including attorneys’ fees, related to the distribution or use of your applications, except to the extent that any claim is based solely on the unmodified distributable code. - c) Distribution Restrictions. You may not: - i. use Microsoft’s trademarks or trade dress in your application in any way that suggests your application comes from or is endorsed by Microsoft; or - ii. modify or distribute the source code of any distributable code so that any part of it becomes subject to any license that requires that the distributable code, any other part of the software, or any of Microsoft’s other intellectual property be disclosed or distributed in source code form, or that others have the right to modify it. - -4. SCOPE OF LICENSE. The software is licensed, not sold. Microsoft reserves all other rights. Unless applicable law gives you more rights despite this limitation, you will not (and have no right to): - a) remove, minimize, block, or modify any notices of Microsoft or its suppliers in the software;software; - b) use the software in any way that is against the law or to create or propagate malware; or - c) share, publish, distribute, or lease the software (except for any distributable code, subject to the terms above), provide the software as a stand-alone offering for others to use, or transfer the software or this agreement to any third party. - -5. Data Protection. There are also some features in the software that may enable you to collect data from users of your applications. If you use these features to enable data collection in your applications, you must comply with applicable law, including providing appropriate notices to and obtaining consent from users of your applications. You can learn more about data collection and use in the help documentation and the privacy statement at https://aka.ms/privacy. Your use of the software operates as your consent to these practices. - -6. CODE OF CONDUCT. By agreeing to these license terms, you’re agreeing that, when using the software, you will follow these rules: - a) Don’t do anything illegal. - b) Don’t engage in any activity that exploits, harms, or threatens to harm children. - c) Don’t send spam. Spam is unwanted or unsolicited bulk email, postings, contact requests, SMS (text messages), or instant messages. - d) Don’t publicly display or use the software to share inappropriate content or material (involving, for example, nudity, bestiality, pornography, offensive language, graphic violence, or criminal activity). - e) Don’t engage in activity that is fraudulent, false or misleading (e.g., asking for money under false pretenses, impersonating someone else, manipulating the software to increase play count, or affect rankings, ratings, or comments). - f) Don’t circumvent any restrictions on access to or availability of the software. - g) Don’t engage in activity that is harmful to you, the software, or others (e.g., transmitting viruses, stalking, posting terrorist content, communicating hate speech, or advocating violence against others). - h) Don’t infringe upon the rights of others (e.g., unauthorized sharing of copyrighted music or other copyrighted material, resale or other distribution of Bing maps, or photographs). - i) Don’t engage in activity that violates the privacy of others. - j) Don’t help others break these rules. - -7. EXPORT RESTRICTIONS. You must comply with all domestic and international export laws and regulations that apply to the software, which include restrictions on destinations, end users, and end use. For further information on export restrictions, visit https://aka.ms/exporting. - -8. SUPPORT SERVICES. Microsoft is not obligated under this agreement to provide any support services for the software. Any support provided is “as is”, “with all faults”, and without warranty of any kind. - -9. ENTIRE AGREEMENT. This agreement, terms referenced herein, and any other terms Microsoft may provide for supplements, updates, or third-party applications, is the entire agreement for the software. - -10. APPLICABLE LAW AND PLACE TO RESOLVE DISPUTES. If you acquired the software in the United States or Canada, the laws of the state or province where you live (or, if a business, where your principal place of business is located) govern the interpretation of this agreement, claims for its breach, and all other claims (including consumer protection, unfair competition, and tort claims), regardless of conflict of laws principles, except that the FAA governs everything related to arbitration. If you acquired the software in any other country, its laws apply, except that the FAA governs everything related to arbitration. If U.S. federal jurisdiction exists, you and Microsoft consent to exclusive jurisdiction and venue in the federal court in King County, Washington for all disputes heard in court (excluding arbitration). If not, you and Microsoft consent to exclusive jurisdiction and venue in the Superior Court of King County, Washington for all disputes heard in court (excluding arbitration). - -11. CONSUMER RIGHTS; REGIONAL VARIATIONS. This agreement describes certain legal rights. You may have other rights, including consumer rights, under the laws of your state or country. Separate and apart from your relationship with Microsoft, you may also have rights with respect to the party from which you acquired the software. This agreement does not change those other rights if the laws of your state or country do not permit it to do so. For example, if you acquired the software in one of the below regions, or mandatory country law applies, then the following provisions apply to you: - a. Australia. You have statutory guarantees under the Australian Consumer Law and nothing in this agreement is intended to affect those rights. - b. Canada. If you acquired this software in Canada, you may stop receiving updates by turning off the automatic update feature, disconnecting your device from the Internet (if and when you re-connect to the Internet, however, the software will resume checking for and installing updates), or uninstalling the software. The product documentation, if any, may also specify how to turn off updates for your specific device or software. - c. Germany and Austria. - • Warranty. The properly licensed software will perform substantially as described in any Microsoft materials that accompany the software. However, Microsoft gives no contractual guarantee in relation to the licensed software. - • Limitation of Liability. In case of intentional conduct, gross negligence, claims based on the Product Liability Act, as well as, in case of death or personal or physical injury, Microsoft is liable according to the statutory law. - • Subject to the foregoing clause ii., Microsoft will only be liable for slight negligence if Microsoft is in breach of such material contractual obligations, the fulfillment of which facilitate the due performance of this agreement, the breach of which would endanger the purpose of this agreement and the compliance with which a party may constantly trust in (so-called "cardinal obligations"). In other cases of slight negligence, Microsoft will not be liable for slight negligence. - -12. DISCLAIMER OF WARRANTY. THE SOFTWARE IS LICENSED “AS IS.” YOU BEAR THE RISK OF USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES, OR CONDITIONS. TO THE EXTENT PERMITTED UNDER APPLICABLE LAWS, MICROSOFT EXCLUDES ALL IMPLIED WARRANTIES, INCLUDING MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. - -13. PRE-RELEASE DISCLAIMER. AS A PRE-RELEASE VERSION, THIS SOFTWARE AND UNDERLYING SERVICES, ARE PROVIDED "AS-IS," "WITH ALL FAULTS," AND "AS AVAILABLE," AND ARE EXCLUDED FROM THE SERVICE LEVEL AGREEMENTS AND LIMITED WARRANTY. Pre-release versions may not be covered by customer support, and may be subject to reduced or different security, compliance and privacy commitments, as further explained in the Microsoft Privacy Statement, Microsoft Azure Trust Center, the Product Terms, the DPA, and any additional notices provided with the software. Where applicable, the following terms in the DPA do not apply to Previews: Processing of Personal Data; GDPR, Data Security. - -14. LIMITATION ON AND EXCLUSION OF DAMAGES. IF YOU HAVE ANY BASIS FOR RECOVERING DAMAGES DESPITE THE PRECEDING DISCLAIMER OF WARRANTY, YOU CAN RECOVER FROM MICROSOFT AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT, OR INCIDENTAL DAMAGES. - - This limitation applies to (a) anything related to the software, services, content (including code) on third party Internet sites, or third party applications; and (b) claims for breach of contract, warranty, guarantee, or condition; strict liability, negligence, or other tort; or any other claim; in each case to the extent permitted by applicable law. - - It also applies even if Microsoft knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your state, province, or country may not allow the exclusion or limitation of incidental, consequential, or other damages. - - Please note: As this software is distributed in Canada, some of the clauses in this agreement are provided below in French. - - Remarque: Ce logiciel étant distribué au Canada, certaines des clauses dans ce contrat sont fournies ci-dessous en français. - - EXONÉRATION DE GARANTIE. Le logiciel visé par une licence est offert « tel quel ». Toute utilisation de ce logiciel est à votre seule risque et péril. Microsoft n’accorde aucune autre garantie expresse. Vous pouvez bénéficier de droits additionnels en vertu du droit local sur la protection des consommateurs, que ce contrat ne peut modifier. La ou elles sont permises par le droit locale, les garanties implicites de qualité marchande, d’adéquation à un usage particulier et d’absence de contrefaçon sont exclues. - - LIMITATION DES DOMMAGES-INTÉRÊTS ET EXCLUSION DE RESPONSABILITÉ POUR LES DOMMAGES. Vous pouvez obtenir de Microsoft et de ses fournisseurs une indemnisation en cas de dommages directs uniquement à hauteur de 5,00 $ US. Vous ne pouvez prétendre à aucune indemnisation pour les autres dommages, y compris les dommages spéciaux, indirects ou accessoires et pertes de bénéfices. - - Cette limitation concerne: - - • tout ce qui est relié au logiciel, aux services ou au contenu (y compris le code) figurant sur des sites Internet tiers ou dans des programmes tiers; et - - • les réclamations au titre de violation de contrat ou de garantie, ou au titre de responsabilité stricte, de négligence ou d’une autre faute dans la limite autorisée par la loi en vigueur. - - Elle s’applique également, même si Microsoft connaissait ou devrait connaître l’éventualité d’un tel dommage. Si votre pays n’autorise pas l’exclusion ou la limitation de responsabilité pour les dommages indirects, accessoires ou de quelque nature que ce soit, il se peut que la limitation ou l’exclusion ci-dessus ne s’appliquera pas à votre égard. - - EFFET JURIDIQUE. Le présent contrat décrit certains droits juridiques. Vous pourriez avoir d’autres droits prévus par les lois de votre pays. Le présent contrat ne modifie pas les droits que vous confèrent les lois de votre pays si celles-ci ne le permettent pas. \ No newline at end of file diff --git a/packages/live-share-turbo/README.md b/packages/live-share-turbo/README.md deleted file mode 100644 index 757eab67a..000000000 --- a/packages/live-share-turbo/README.md +++ /dev/null @@ -1,291 +0,0 @@ -# Microsoft Live Share Turbo - -**DISCLAIMER:** This package is in preview and experimental. We are not yet committed to maintaining this package and may make breaking changes at any time. We may decide to move some or all of these features into the main `live-share` package at a future date. Read this package's [license](./LICENSE) for more information. - -Easily create collaborative apps, powered by [Fluid Framework](https://fluidframework.com/). This package is an experimental, alternative approach to building Fluid & Live Share applications that attempts to make it simpler to use dynamic distributed-data structures. One of the main benefits of Fluid is the efficient, hierarchal, and ultra-fast remote synchronized application state. Vanilla Fluid is highly customizable, allowing you to nest references to DDS objects within other ones. This is powerful but can be cumbersome to work with. By taking a more opinionated stance, Live Share Turbo makes it easy to leverage dynamic objects more easily than ever before. - -In traditional Fluid applications, you must define your Fluid container schema up front. In this package, you load data objects on the fly by simply providing a unique identifier for your object. If a data object matching that identifier exists already exists, the SDK will use that one; otherwise, a new one will be created on your behalf. Fluid Framework's `ConsensusRegisterCollection` object is used to ensure that only one user will create the DDS for each unique identifier. - -Here is a simple example of how to get started: - -```javascript -import { LiveShareHost } from "@microsoft/teams-js"; -import { LiveShareTurboClient } from "@microsoft/live-share-turbo"; -import { SharedMap } from "fluid-framework"; - -// Initialize the LiveShareTurboClient and join the session -const host = LiveShareHost.create(); -const client = new LiveShareTurboClient(host); -await client.join(); -// Setup collaborative objects (e.g., SharedMap) as needed during your application's runtime -const sharedMap = await client.getDDS( - "UNIQUE-KEY", - SharedMap, - (sharedMap) => { - // Use this optional callback to set initial values for the data object - sharedMap.set("foo", "bar"); - } -); -sharedMap.on("valueChanged", (changed, local) => { - const value = sharedMap.get(changed.key); - // Update your app to reflect the most recent state -}); -``` - -If you use React, we recommend using the specially optimized [Live Share React package](../live-share-react/README.md). - -You can find our API reference documentation at [aka.ms/livesharedocs](https://aka.ms/livesharedocs). - -## Installing - -To add the latest version of the SDK to your application using NPM: - -```bash -npm install fluid-framework @fluidframework/azure-client @microsoft/live-share @microsoft/live-share-turbo --save -``` - -or using [Yarn](https://yarnpkg.com/): - -```bash -yarn add fluid-framework @fluidframework/azure-client @microsoft/live-share @microsoft/live-share-turbo --save -``` - -## Building the extension - -After cloning the [GitHub repository](https://www.github.com/microsoft/live-share-sdk), navigate to the root folder and perform: - -```bash -npm install -npm run build -``` - -This will use npm workspaces to hoist and build all dependencies. - -## Introduction - -There are two clients that you may use depending on your scenario: `LiveShareTurboClient` for Live Share, and `AzureTurboClient` for Azure Fluid Relay. These are used for connecting to Fluid sessions, and are structured differently than the more traditional `LiveShareClient` and `AzureClient` respectively. These clients expose a `.getDDS` function, which under the hood uses `DynamicObjectManager` to dynamically get or create a given DDS. It also exposes a default `SharedMap` called `stateMap`, which you can use in your application to track basic app state. - -### How this package compares against vanilla Fluid / Live Share - -Normally with Fluid you must define the DDS objects you want to use up front in the `ContainerSchema`. This can feel rigid and makes it harder to add new features over time. With Live Share Turbo, you don't need to do that -- though you can -- because it abstracts out some of the more powerful but verbose aspects of Fluid. - -The following example shows how you might build a synchronized counter using vanilla Fluid Framework: - -```javascript -import { SharedMap } from "fluid-framework"; -import { LiveShareClient } from "@microsoft/live-share"; -import { LiveShareHost } from "@microsoft/teams-js"; - -// Initialize LiveShareClient -const host = LiveShareHost.create(); -const client = new LiveShareClient(host); -// Define your schema and join the container -const schema = { - initialObjects: { - countMap: SharedMap, - }, -} -let count = 0; -async function onFirstInitializeContainer(container) { - // Set initial value in sharedMap when container is first initialized - container.initialObjects.countMap.set("count", count); -} -const { container } = await client.joinContainer(schema, onFirstInitializeContainer); -const { countMap } = container.initialObjects; -// Listen for changes to the count and get the initial value -countMap.on("valueChanged", () => { - count = countMap.get("count"); -}) -count = countMap.get("count"); -// Button handler to increment count -document.getElementById("my-button").onclick = () => { - countMap.set("count", count + 1); -} -``` - -This works fine in many situations, but assumes that your `initialObjects` will not change after shipping your app in production. It also assumes that all collaborative objects exist at the time your container is created. Fortunately, Fluid supports something called `dynamicObjectTypes`, which allow you to create new objects on the fly and store references to them within a `SharedMap`, `SharedDirectory`, or `SharedTree`. - -Here is a code snippet showing how you might make the above example more scalable using dynamic objects in vanilla Fluid Framework: - -```javascript -import { SharedMap } from "fluid-framework"; -import { LiveShareClient } from "@microsoft/live-share"; -import { LiveShareHost } from "@microsoft/teams-js"; - -// Initialize LiveShareClient -const host = LiveShareHost.create(); -const client = new LiveShareClient(host); -// Define your schema and join the container -const schema = { - initialObjects: { - sharedMap: SharedMap - }, - dynamicObjectTypes: [SharedMap] -} -async function onFirstInitializeContainer(container) { - // Set initial value for dynamic countMap into sharedMap - const newCountMap = await container.create(SharedMap); - container.initialObjects.sharedMap.set("countMap", newCountMap.handle); - // Set initial count value - newCountMap.set("count", 0); -}; -const { container } = await client.joinContainer(schema, onFirstInitializeContainer); -// Define callback for setting up dynamic countMap -let countMap; -let count = 0; -async function setupCountMap() { - if (countMap) { - // if we already have a countMap set, we dispose the object - countMap.dispose(); - } - const countMapHandle = countMap.get("countMap"); - if (!countMapHandle) return; - countMap = await countMapHandle.get(); - // Listen for changes to the count - countMap.on("valueChanged", () => { - count = countMap.get("count"); - }); - // Get initial count value - count = countMap.get("count"); -} -// Listen for changes to countMap handle in sharedMap and get initial value -const { sharedMap } = container.initialObjects; -sharedMap.on("valueChanged", async (changed) => { - if (changed.key === "countMap") { - setupCountMap(); - } -}); -setupCountMap(); -// Button handler to increment count -document.getElementById("my-button").onclick = () => { - if (countMap) { - countMap.set("count", count + 1); - } -} -``` - -The above sample shows why Fluid is so powerful, albeit slightly complicated. The ability to have nested DDS objects in your code allows you to build robust collaborative apps that scale over time. Live Share Turbo leverages the power of dynamic objects with less code. It also makes using `initialObjects` optional. - -Here is a simple example showing how you could achieve the same behavior as above using Live Share Turbo: - -```javascript -import { LiveShareHost } from "@microsoft/live-share"; -import { LiveShareTurboClient } from "@microsoft/live-share-turbo"; -import { SharedMap } from "fluid-framework"; - -// Join the Fluid session -const host = LiveShareHost.create(); -const client = LiveShareTurboClient(host); -await client.join(); -// Get/create a TurboSharedMap instance that corresponds to a given unique identifier -const countMap = await client.getDDS("countMap", SharedMap, (initialMap) => { - // Callback to setup initial values when the DDS is first created - initialMap.set("count", 0); -}); -// Listen for changes to the count and get the initial value -let count; -countMap.on("valueChanged", () => { - count = countMap.get("count"); -}); -count = countMap.get("count"); -// Button handler to increment count -document.getElementById("my-button").onclick = () => { - countMap.set("count", count + 1); -}; -``` - -### Avoiding data loss - -In some circumstances while using this application -- particularly in cases of high latency while using Fluid's `Shared*` objects -- data loss is possible if multiple users attempt to create new data objects for the same key in short periods of time. This is mitigated by using `ConsensusRegisterCollection` to ensure that only one user is responsible for creating each DDS, but this will require more testing before we can have 100% confidence that data loss is not possible. - -To minimize this risk, you can also use the `initialObjects` prop when first creating a Fluid container and use identifiers for objects in a list. This has similar constraints as regular Fluid -- such as migrating schemas after first creating the container -- but is useful in scenarios where up-front data loss is unacceptable. Here is an example of how to do this in your application: - -```javascript -import { LiveShareHost } from "@microsoft/teams-js"; -import { LiveShareTurboClient } from "@microsoft/live-share-turbo"; -import { SharedMap } from "fluid-framework"; -import { v4 as uuid } from "uuid"; - -// Join the Fluid session -const host = LiveShareHost.create(); -const client = LiveShareTurboClient(host); -const initialObjects = { - taskBoardMap: SharedMap, -}; -await client.join(initialObjects); -// Listen for changes to the task boards and get the initial value -const taskBoardMap = await client.getDDS("taskBoardMap", SharedMap); -let taskBoards; -taskBoardMap.on("valueChanged", () => { - // Update UI with available task boards - taskBoards = taskBoardMap.entries(); -}); -taskBoards = taskBoardMap.entries(); - -// Button click handler for creating a new task board -document.getElementById("create-task-board").onclick = async () => { - // Dynamically create a new task list map - const id = uuid(); - const taskListMap = await client.getDDS(`taskListMap-${id}`, SharedMap); - // Insert the new task board object into the taskBoardMap - taskBoardMap.set(id, { - name: "New list" - }); - // TODO: Open the task list UI for the newly taskListMap -}; -``` - -**Note**: Depending on your scenario, this package might not be a good fit for your application. While many apps work great with this system, we recommend testing thoroughly before committing this package to production. - -### Accessing the Fluid container - -If you want to access the Fluid container or audience used by `LiveShareTurboClient` or `AzureTurboClient`, such as to create a Fluid object the "traditional" Fluid way, you can easily access it through the following API: - -```javascript -import { LiveShareHost } from "@microsoft/teams-js"; -import { LiveShareTurboClient } from "@microsoft/live-share-turbo"; - -const host = LiveShareHost.create(); -const client = LiveShareTurboClient(host); -// Option 1: get from join -const { container, audience } = await client.join(); -// Option 2: use client results -if (client.results) { - const { container, audience } = client.results; -} -``` - -## Code samples - -| Sample name | Description | Javascript | -| ----------------- | ----------------------------------------------------------------------- | ----------------------------------------------------- | -| Dice Roller Turbo | Enable all connected clients to roll several dice and view the result. | [View](../../samples/javascript/05.dice-roller-turbo) | - -## Package Compatibility - -The Live Share SDK contains dependencies for [@microsoft/teams-js](https://www.npmjs.com/package/@microsoft/teams-js) and [fluid-framework](https://www.npmjs.com/package/fluid-framework) packages among others. Both of these packages are sensitive to the package version your app any libraries use. You will likely run into issues if the package version your app uses doesn't match the version other libraries you depend on use. - -**It is critical that your app use the package dependencies listed in the table below.** Lookup the version of the `@microsoft/live-share` you're using and set any other dependencies in your package.json file to match: - -| @microsoft/live-share | @microsoft/teams-js | fluid-framework | @microsoft/live-share-\* | @fluidframework/azure-client | @microsoft/TeamsFx | @microsoft/TeamsFx-react | -| --------------------- | -------------------- | --------------- | -------------------------- | ---------------------------- | ------------------------------- | ------------------------------- | -| ^1.0.0 | ^2.11.0 | ^1.2.3 | ^1.0.0 | ^1.0.0 | ^2.5.0 | ^2.5.0 | - -## Contributing - -There are several ways you can [contribute](../../CONTRIBUTING.md) to this project: - -- [Submit bugs](https://github.com/microsoft/live-share-sdk/issues) and help us verify fixes as they are checked in. -- Review the source code changes. -- Engage with other Live Share developers on [StackOverflow](https://stackoverflow.com/questions/tagged/live-share). -- [Contribute bug fixes](../../CONTRIBUTING.md). - -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact with any additional questions or comments. - -## Reporting Security Issues - -Security issues and bugs should be reported privately, via email, to the Microsoft Security Response Center (MSRC) at . You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Further information, including the [MSRC PGP](https://technet.microsoft.com/security/dn606155) key, can be found in the [Security TechCenter](https://technet.microsoft.com/security/default). - -Copyright (c) Microsoft Corporation. All rights reserved. - -Licensed under a special [Microsoft](./LICENSE) License. diff --git a/packages/live-share-turbo/package.json b/packages/live-share-turbo/package.json deleted file mode 100644 index b3d666c91..000000000 --- a/packages/live-share-turbo/package.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "name": "@microsoft/live-share-turbo", - "version": "1.4.0-preview.0", - "description": "Alternative & lightweight way to build collaborative apps using Microsoft's Fluid Framework & Live Share.", - "author": "Microsoft", - "license": "SEE LICENSE IN LICENSE", - "main": "./bin/index.js", - "types": "./bin/index.d.ts", - "scripts": { - "clean": "npx shx rm -rf bin", - "build": "tsc -p tsconfig.build.json", - "test": "start-server-and-test start:server 7070 test:local-main", - "test:debug": "start-server-and-test start:server 7070 test:local-debug", - "start:server": "npx tinylicious@latest > tinylicious.log 2>&1", - "test:local-main": "ts-mocha --config ./src/test/.mocharc.js src/**/*.spec.ts --timeout 10000 -r jsdom-global/register", - "test:local-debug": "ts-mocha --config ./src/test/.mocharc.js src/**/*.spec.ts --inspect-brk -r jsdom-global/register", - "test:coverage": "nyc --reporter=html --reporter=text --reporter=text-summary npm test" - }, - "dependencies": { - "@fluidframework/register-collection": "^1.3.6" - }, - "devDependencies": { - "@fluidframework/azure-client": "^1.1.1", - "@fluidframework/test-client-utils": "^1.3.6", - "@fluidframework/test-runtime-utils": "^1.3.6", - "@fluidframework/test-utils": "^1.3.6", - "@fluidframework/test-version-utils": "^1.3.6", - "@microsoft/live-share": "1.4.0", - "@types/assert": "^1.5.6", - "@types/mocha": "^10.0.1", - "@types/node": "^20.2.3", - "@types/uuid": "9.0.1", - "fluid-framework": "^1.3.6", - "jsdom-global": "^3.0.2", - "jsdom": "^21.1.0", - "mocha": "^10.2.0", - "nyc": "^15.1.0", - "start-server-and-test": "^2.0.0", - "ts-mocha": "^10.0.0", - "typescript": "^5.0.4" - }, - "peerDependencies": { - "@fluidframework/azure-client": "^1.0.0", - "@microsoft/live-share": "1.4.0", - "fluid-framework": "^1.2.3" - }, - "repository": { - "directory": "packages/live-share-turbo", - "type": "git", - "url": "https://github.com/microsoft/live-share-sdk" - }, - "homepage": "https://aka.ms/teamsliveshare", - "bugs": { - "url": "https://github.com/microsoft/live-share-sdk/issues" - } -} diff --git a/packages/live-share-turbo/src/AzureTurboClient.ts b/packages/live-share-turbo/src/AzureTurboClient.ts deleted file mode 100644 index 7cbf810bf..000000000 --- a/packages/live-share-turbo/src/AzureTurboClient.ts +++ /dev/null @@ -1,136 +0,0 @@ -/*! - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Microsoft Live Share SDK License. - */ - -import { - ContainerSchema, - IFluidContainer, - LoadableObjectClassRecord, -} from "fluid-framework"; -import { - AzureClient, - AzureClientProps, - AzureContainerServices, -} from "@fluidframework/azure-client"; -import { - AzureLiveShareHost, - ILiveShareHost, - LiveShareRuntime, - getLiveContainerSchema, -} from "@microsoft/live-share"; -import { FluidTurboClient } from "./FluidTurboClient"; - -/** - * The `FluidTurboClient` implementation for the `AzureClient`. - * @see FluidTurboClient - */ -export class AzureTurboClient extends FluidTurboClient { - private _host: ILiveShareHost; - private _client: AzureClient; - private _results: - | { - container: IFluidContainer; - services: AzureContainerServices; - } - | undefined; - private _runtime: LiveShareRuntime; - - /** - * Creates a new client instance using configuration parameters. - * @param props - Properties for initializing a new AzureClient instance - */ - constructor( - props: AzureClientProps, - host: ILiveShareHost = AzureLiveShareHost.create(true) - ) { - super(); - this._client = new AzureClient(props); - this._host = host; - this._runtime = new LiveShareRuntime(this._host); - } - - /** - * Get the Fluid join container results - */ - public override get results(): - | { - container: IFluidContainer; - services: AzureContainerServices; - } - | undefined { - return this._results; - } - - /** - * Setting for whether `LiveDataObject` instances using `LiveObjectSynchronizer` can send background updates. - * Default value is `true`. - * - * @remarks - * This is useful for scenarios where there are a large number of participants in a session, since service performance degrades as more socket connections are opened. - * Intended for use when a small number of users are intended to be "in control", such as the `LiveFollowMode` class's `startPresenting()` feature. - * Set to true when the user is eligible to send background updates (e.g., "in control"), or false when that user is not in control. - * This setting will not prevent the local user from explicitly changing the state of objects using `LiveObjectSynchronizer`, such as `.set()` in `LiveState`. - * Impacts background updates of `LiveState`, `LivePresence`, `LiveTimer`, and `LiveFollowMode`. - */ - public get canSendBackgroundUpdates(): boolean { - return this._runtime.canSendBackgroundUpdates; - } - - public set canSendBackgroundUpdates(value: boolean) { - this._runtime.canSendBackgroundUpdates = value; - } - - /** - * Creates a new detached container instance in the Azure Fluid Relay. - * @param initialObjects Optional. Fluid ContainerSchema initialObjects. - * @param host Optional. ILiveShareHost implementation to use when using Live Share DDS's. - * @returns New detached container instance along with associated services. - */ - public async createContainer( - initialObjects?: LoadableObjectClassRecord - ): Promise<{ - container: IFluidContainer; - services: AzureContainerServices; - }> { - const schema = this.getInjectedContainerSchema(initialObjects); - this._results = await this._client.createContainer(schema); - if (this._host instanceof AzureLiveShareHost) { - this._host.setAudience(this._results.services.audience); - } - await this._runtime.start(); - return this._results; - } - - /** - * Accesses the existing container given its unique ID in the Azure Fluid Relay. - * @param id - Unique ID of the container in Azure Fluid Relay. - * @param initialObjects Optional. Fluid ContainerSchema initialObjects. - * @param host Optional. ILiveShareHost implementation to use when using Live Share DDS's. - * @returns Existing container instance along with associated services. - */ - public async getContainer( - id: string, - initialObjects?: LoadableObjectClassRecord - ): Promise<{ - container: IFluidContainer; - services: AzureContainerServices; - }> { - const schema = this.getInjectedContainerSchema(initialObjects); - this._results = await this._client.getContainer(id, schema); - if (this._host instanceof AzureLiveShareHost) { - this._host.setAudience(this._results.services.audience); - } - await this._runtime.start(); - return this._results; - } - - private getInjectedContainerSchema( - initialObjects?: LoadableObjectClassRecord - ): ContainerSchema { - return getLiveContainerSchema( - this.getContainerSchema(initialObjects), - this._runtime - ); - } -} diff --git a/packages/live-share-turbo/src/FluidTurboClient.ts b/packages/live-share-turbo/src/FluidTurboClient.ts deleted file mode 100644 index 531fc03a6..000000000 --- a/packages/live-share-turbo/src/FluidTurboClient.ts +++ /dev/null @@ -1,161 +0,0 @@ -/*! - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Microsoft Live Share SDK License. - */ - -import { - IFluidContainer, - LoadableObjectClass, - LoadableObjectClassRecord, - SharedMap, -} from "fluid-framework"; -import { AzureContainerServices } from "@fluidframework/azure-client"; -import { IFluidLoadable, FluidObject } from "@fluidframework/core-interfaces"; -import { IFluidTurboClient } from "./interfaces/IFluidTurboClient"; -import { DynamicObjectManager } from "./dds-objects"; -import { DynamicObjectRegistry } from "@microsoft/live-share"; -import { BASE_CONTAINER_SCHEMA } from "./internals"; - -/** - * Base class for building Fluid Turbo clients. - * @remarks - * Unlike other Fluid clients, the turbo client wraps functionality regularly exposed through an `IFluidContainer`. This is due to the more opinionated - * nature of this package than vanilla Fluid Framework, where developers do not define a full `ContainerSchema` themselves and objects are loaded dynamically. - */ -export abstract class FluidTurboClient implements IFluidTurboClient { - private _awaitConnectedPromise?: Promise; - - /** - * Get the Fluid join container results - */ - public abstract get results(): - | { - container: IFluidContainer; - services: AzureContainerServices; - } - | undefined; - - /** - * @see IFluidTurboClient.stateMap - */ - public get stateMap(): SharedMap | undefined { - if (this.results) { - return this.results.container.initialObjects - .TURBO_STATE_MAP as SharedMap; - } - return undefined; - } - - /** - * Setting for whether `LiveDataObject` instances using `LiveObjectSynchronizer` can send background updates. - * Default value is `true`. - * - * @remarks - * This is useful for scenarios where there are a large number of participants in a session, since service performance degrades as more socket connections are opened. - * Intended for use when a small number of users are intended to be "in control", such as the `LiveFollowMode` class's `startPresenting()` feature. - * There should always be at least one user in the session that has `canSendBackgroundUpdates` set to true. - * Set to true when the user is eligible to send background updates (e.g., "in control"), or false when that user is not in control. - * This setting will not prevent the local user from explicitly changing the state of objects using `LiveObjectSynchronizer`, such as `.set()` in `LiveState`. - * Impacts background updates of `LiveState`, `LivePresence`, `LiveTimer`, and `LiveFollowMode`. - */ - public abstract get canSendBackgroundUpdates(): boolean; - - public abstract set canSendBackgroundUpdates(value: boolean); - - private get dynamicObjects(): DynamicObjectManager | undefined { - if (this.results) { - return this.results.container.initialObjects - .TURBO_DYNAMIC_OBJECTS as DynamicObjectManager; - } - return undefined; - } - - /** - * @see IFluidTurboClient.getDDS - */ - public async getDDS< - T extends IFluidLoadable = FluidObject & IFluidLoadable - >( - objectKey: string, - objectClass: LoadableObjectClass, - onDidFirstInitialize?: (dds: T) => void - ): Promise { - // The uniqueKey key makes the developer provided uniqueKey never conflict across different DDS objects - if (!this.results) { - throw new Error( - "FluidTurboClient getDDS: cannot call until successful get/create/join FluidContainer" - ); - } - if (!this.dynamicObjects) { - throw new Error( - "FluidTurboClient: getDDS must have valid dynamicObjects DynamicObjectManager" - ); - } - await this.waitUntilConnected(); - const initialDDS = this.results.container.initialObjects[objectKey] as - | T - | undefined; - if (initialDDS !== undefined) { - return initialDDS; - } - const uniqueKey = `<${objectClass.name}>:${objectKey}`; - const response = await this.dynamicObjects.getDDS( - uniqueKey, - objectClass, - this.results.container - ); - if (response.created) { - onDidFirstInitialize?.(response.dds); - } - return response.dds; - } - - /** - * Get the container schema to use within a `FluidTurboClient` container. - * - * @param initialObjects Optional. Initial objects to add to the schema - * @returns a `ContainerSchema` record to use in a Fluid container - */ - protected getContainerSchema(initialObjects?: LoadableObjectClassRecord) { - return { - initialObjects: { - ...BASE_CONTAINER_SCHEMA.initialObjects, - ...initialObjects, - }, - // Get the static registry of LoadableObjectClass types. - dynamicObjectTypes: [ - ...DynamicObjectRegistry.dynamicLoadableObjects.values(), - ], - }; - } - - private async waitUntilConnected(): Promise { - if (this._awaitConnectedPromise) { - return this._awaitConnectedPromise; - } - this._awaitConnectedPromise = new Promise((resolve, reject) => { - if (!this.results?.container) { - reject( - new Error( - "FluidTurboClient awaitConnected: cannot load DDS without a Fluid container" - ) - ); - this._awaitConnectedPromise = undefined; - } else { - const onConnected = () => { - this.results?.container.off("connected", onConnected); - resolve(); - }; - // Wait until connected event to ensure we have the latest document - // and don't accidentally override a dds handle recently created - // by another client - if (this.results.container.connectionState === 2) { - resolve(); - } else { - this.results.container.on("connected", onConnected); - } - } - }); - return this._awaitConnectedPromise; - } -} diff --git a/packages/live-share-turbo/src/LiveShareTurboClient.ts b/packages/live-share-turbo/src/LiveShareTurboClient.ts deleted file mode 100644 index 36b59c24e..000000000 --- a/packages/live-share-turbo/src/LiveShareTurboClient.ts +++ /dev/null @@ -1,104 +0,0 @@ -/*! - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Microsoft Live Share SDK License. - */ - -import { IFluidContainer, LoadableObjectClassRecord } from "fluid-framework"; -import { - LiveShareClient, - ILiveShareClientOptions, - ILiveShareHost, - ILiveShareJoinResults, -} from "@microsoft/live-share"; -import { FluidTurboClient } from "./FluidTurboClient"; - -/** - * The `FluidTurboClient` implementation for the `LiveShareClient`. - * @see FluidTurboClient - */ -export class LiveShareTurboClient extends FluidTurboClient { - private _client: LiveShareClient; - private _results: ILiveShareJoinResults | undefined; - - /** - * Creates a new `LiveShareTurbo` instance. - * @param host Host for the current Live Share session. - * @param options Optional. Configuration options for the client. - */ - constructor(host: ILiveShareHost, options?: ILiveShareClientOptions) { - super(); - this._client = new LiveShareClient(host, options); - } - - /** - * If true the client is configured to use a local test server. - */ - public get isTesting(): boolean { - return this._client.isTesting; - } - - /** - * Number of times the client should attempt to get the ID of the container to join for the - * current context. - */ - public get maxContainerLookupTries(): number { - return this._client.maxContainerLookupTries; - } - - /** - * Set number of times the client should attempt to get the ID of the container to join for the - * current context. - */ - public set maxContainerLookupTries(value: number) { - this._client.maxContainerLookupTries = value; - } - - /** - * Get the Fluid join container results - */ - public override get results(): ILiveShareJoinResults | undefined { - return this._results; - } - - /** - * Setting for whether `LiveDataObject` instances using `LiveObjectSynchronizer` can send background updates. - * Default value is `true`. - * - * @remarks - * This is useful for scenarios where there are a large number of participants in a session, since service performance degrades as more socket connections are opened. - * Intended for use when a small number of users are intended to be "in control", such as the `LiveFollowMode` class's `startPresenting()` feature. - * Set to true when the user is eligible to send background updates (e.g., "in control"), or false when that user is not in control. - * This setting will not prevent the local user from explicitly changing the state of objects using `LiveObjectSynchronizer`, such as `.set()` in `LiveState`. - * Impacts background updates of `LiveState`, `LivePresence`, `LiveTimer`, and `LiveFollowMode`. - */ - public get canSendBackgroundUpdates(): boolean { - return this._client.canSendBackgroundUpdates; - } - - public set canSendBackgroundUpdates(value: boolean) { - this._client.canSendBackgroundUpdates = value; - } - - /** - * Connects to the fluid container for the current teams context. - * - * @remarks - * The first client joining the container will create the container resulting in the - * `onContainerFirstCreated` callback being called. This callback can be used to set the initial - * state of of the containers object prior to the container being attached. - * @param initialObjects Optional. Fluid ContainerSchema initialObjects. - * @param onContainerFirstCreated Optional. Callback that's called when the container is first created. - * @returns The fluid `container` and `services` objects to use along with a `created` flag that if true means the container had to be created. - */ - public async join( - initialObjects?: LoadableObjectClassRecord, - onContainerFirstCreated?: (container: IFluidContainer) => void - ): Promise { - const schema = this.getContainerSchema(initialObjects); - this._results = await this._client.joinContainer( - schema, - onContainerFirstCreated - ); - return this._results; - } -} diff --git a/packages/live-share-turbo/src/dds-objects/index.ts b/packages/live-share-turbo/src/dds-objects/index.ts deleted file mode 100644 index 1fadc3971..000000000 --- a/packages/live-share-turbo/src/dds-objects/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./DynamicObjectManager"; diff --git a/packages/live-share-turbo/src/index.ts b/packages/live-share-turbo/src/index.ts deleted file mode 100644 index fb806023a..000000000 --- a/packages/live-share-turbo/src/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from "./AzureTurboClient"; -export * from "./LiveShareTurboClient"; -export * from "./FluidTurboClient"; -export * from "./dds-objects"; -export * from "./interfaces"; diff --git a/packages/live-share-turbo/src/interfaces/IFluidTurboClient.ts b/packages/live-share-turbo/src/interfaces/IFluidTurboClient.ts deleted file mode 100644 index a4499dfd8..000000000 --- a/packages/live-share-turbo/src/interfaces/IFluidTurboClient.ts +++ /dev/null @@ -1,42 +0,0 @@ -/*! - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Microsoft Live Share SDK License. - */ - -import { LoadableObjectClass, SharedMap } from "fluid-framework"; -import { IFluidLoadable, FluidObject } from "@fluidframework/core-interfaces"; - -export interface IFluidTurboClient { - /** - * Default SharedMap included in all clients for the purposes of tracking simple app state - */ - get stateMap(): SharedMap | undefined; - /** - * Setting for whether `LiveDataObject` instances using `LiveObjectSynchronizer` can send background updates. - * Default value is `true`. - * - * @remarks - * This is useful for scenarios where there are a large number of participants in a session, since service performance degrades as more socket connections are opened. - * Intended for use when a small number of users are intended to be "in control", such as the `LiveFollowMode` class's `startPresenting()` feature. - * There should always be at least one user in the session that has `canSendBackgroundUpdates` set to true. - * Set to true when the user is eligible to send background updates (e.g., "in control"), or false when that user is not in control. - * This setting will not prevent the local user from explicitly changing the state of objects using `LiveObjectSynchronizer`, such as `.set()` in `LiveState`. - * Impacts background updates of `LiveState`, `LivePresence`, `LiveTimer`, and `LiveFollowMode`. - */ - get canSendBackgroundUpdates(): boolean; - set canSendBackgroundUpdates(value: boolean); - /** - * Callback to load a Fluid DDS for a given key. If the object does not already exist, a new one will be created. - * - * @template T Type of Fluid object to load. - * @param objectKey unique key for the Fluid DDS you'd like to load - * @param objectClass Fluid LoadableObjectClass you'd like to load of type T - * @param onDidFirstInitialize Optional. Callback that is used when the object was initially created. - * @returns DDS object corresponding to `objectKey` - */ - getDDS & IFluidLoadable>( - objectKey: string, - objectClass: LoadableObjectClass, - onDidFirstInitialize?: (dds: T) => void - ): Promise; -} diff --git a/packages/live-share-turbo/src/interfaces/index.ts b/packages/live-share-turbo/src/interfaces/index.ts deleted file mode 100644 index 1b6e69f4e..000000000 --- a/packages/live-share-turbo/src/interfaces/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./IFluidTurboClient"; diff --git a/packages/live-share-turbo/src/internals/debounce.ts b/packages/live-share-turbo/src/internals/debounce.ts deleted file mode 100644 index c2ef38033..000000000 --- a/packages/live-share-turbo/src/internals/debounce.ts +++ /dev/null @@ -1,26 +0,0 @@ -/*! - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Microsoft Live Share SDK License. - */ - -export function debounce( - fn: (...args: any[]) => R, - ms: number -): [(...args: any[]) => Promise, () => void] { - let timer: NodeJS.Timeout; - - const debouncedFunc = (...args: any[]): Promise => - new Promise((resolve) => { - if (timer) { - clearTimeout(timer); - } - - timer = setTimeout(() => { - resolve(fn(args)); - }, ms); - }); - - const teardown = () => timer && clearTimeout(timer); - - return [debouncedFunc, teardown]; -} diff --git a/packages/live-share-turbo/src/internals/index.ts b/packages/live-share-turbo/src/internals/index.ts deleted file mode 100644 index af9b24abf..000000000 --- a/packages/live-share-turbo/src/internals/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./schema"; -export * from "./debounce"; diff --git a/packages/live-share-turbo/src/internals/schema.ts b/packages/live-share-turbo/src/internals/schema.ts deleted file mode 100644 index b4d44f6e5..000000000 --- a/packages/live-share-turbo/src/internals/schema.ts +++ /dev/null @@ -1,22 +0,0 @@ -/*! - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Microsoft Live Share SDK License. - */ - -import { DynamicObjectRegistry } from "@microsoft/live-share"; -import { - ContainerSchema, - LoadableObjectClassRecord, - SharedMap, -} from "fluid-framework"; -import { DynamicObjectManager } from "../dds-objects"; - -/** - * @hidden - */ -export const BASE_CONTAINER_SCHEMA: ContainerSchema = { - initialObjects: { - TURBO_STATE_MAP: SharedMap, - TURBO_DYNAMIC_OBJECTS: DynamicObjectManager, - }, -}; diff --git a/packages/live-share-turbo/src/test/getContainerSchema.spec.ts b/packages/live-share-turbo/src/test/getContainerSchema.spec.ts deleted file mode 100644 index f0dff60df..000000000 --- a/packages/live-share-turbo/src/test/getContainerSchema.spec.ts +++ /dev/null @@ -1,68 +0,0 @@ -/*! - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Microsoft Live Share SDK License. - */ - -import { LiveEvent, TestLiveShareHost } from "@microsoft/live-share"; -import { strict as assert } from "assert"; -import { - LoadableObjectClassRecord, - SharedMap, - SharedString, -} from "fluid-framework"; -import { LiveShareTurboClient } from "../LiveShareTurboClient"; - -class TestLiveShareTurboClient extends LiveShareTurboClient { - // exposes protected method as public - public getContainerSchema(initialObjects?: LoadableObjectClassRecord) { - return super.getContainerSchema(initialObjects); - } -} - -describe("getContainerSpec", () => { - it("Container schema should have expected initialObjects with no additional initialObjects defined", () => { - const testLiveShareTurboClient = new TestLiveShareTurboClient( - TestLiveShareHost.create() - ); - const schema1 = testLiveShareTurboClient.getContainerSchema(); - assert( - schema1.initialObjects.TURBO_STATE_MAP !== undefined, - "TURBO_STATE_MAP is undefined" - ); - assert( - schema1.initialObjects.TURBO_DYNAMIC_OBJECTS !== undefined, - "TURBO_DYNAMIC_OBJECTS is undefined" - ); - }); - - it("Container schema should have expected initialObjects with no additional initialObjects defined", () => { - const testLiveShareTurboClient = new TestLiveShareTurboClient( - TestLiveShareHost.create() - ); - const schema1 = testLiveShareTurboClient.getContainerSchema({ - testMap1: SharedMap, - sharedString1: SharedString, - sharedEvent1: LiveEvent, - }); - assert( - schema1.initialObjects.TURBO_STATE_MAP !== undefined, - "TURBO_STATE_MAP is undefined" - ); - assert( - schema1.initialObjects.TURBO_DYNAMIC_OBJECTS !== undefined, - "TURBO_DYNAMIC_OBJECTS is undefined" - ); - assert( - schema1.initialObjects.testMap1 !== undefined, - "testMap1 is undefined" - ); - assert( - schema1.initialObjects.sharedString1 !== undefined, - "sharedString1 is undefined" - ); - assert( - schema1.initialObjects.sharedEvent1 !== undefined, - "sharedEvent1 is undefined" - ); - }); -}); diff --git a/packages/live-share-turbo/tsconfig.build.json b/packages/live-share-turbo/tsconfig.build.json deleted file mode 100644 index 9d8cab4a6..000000000 --- a/packages/live-share-turbo/tsconfig.build.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ - }, - "exclude": [ - "test/**/*.ts" - ] - } \ No newline at end of file diff --git a/packages/live-share-turbo/tsconfig.json b/packages/live-share-turbo/tsconfig.json deleted file mode 100644 index 258994400..000000000 --- a/packages/live-share-turbo/tsconfig.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "compilerOptions": { - /* Visit https://aka.ms/tsconfig.json to read more about this file */ - - /* Basic Options */ - // "incremental": true, /* Enable incremental compilation */ - "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ - "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ - "lib": ["es2020","DOM"], /* Specify library files to be included in the compilation. */ - "allowJs": false, /* Allow javascript files to be compiled. */ - // "checkJs": true, /* Report errors in .js files. */ - // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ - "declaration": true, /* Generates corresponding '.d.ts' file. */ - "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ - "sourceMap": true, /* Generates corresponding '.map' file. */ - // "outFile": "./", /* Concatenate and emit output to single file. */ - "outDir": "./bin", /* Redirect output structure to the directory. */ - // "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ - // "composite": true, /* Enable project compilation */ - // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ - // "removeComments": true, /* Do not emit comments to output. */ - // "noEmit": true, /* Do not emit outputs. */ - // "importHelpers": true, /* Import emit helpers from 'tslib'. */ - // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ - // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ - - /* Strict Type-Checking Options */ - "strict": true, /* Enable all strict type-checking options. */ - // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* Enable strict null checks. */ - // "strictFunctionTypes": true, /* Enable strict checking of function types. */ - // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ - // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ - // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ - // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ - - /* Additional Checks */ - // "noUnusedLocals": true, /* Report errors on unused locals. */ - // "noUnusedParameters": true, /* Report errors on unused parameters. */ - // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ - // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - - /* Module Resolution Options */ - // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ - // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ - // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ - // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ - // "typeRoots": [], /* List of folders to include type definitions from. */ - // "types": [], /* Type declaration files to be included in compilation. */ - // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ - "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ - // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - - /* Source Map Options */ - // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ - // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ - - /* Experimental Options */ - // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ - // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ - - /* Advanced Options */ - "skipLibCheck": true, /* Skip type checking of declaration files. */ - "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ - }, - "exclude": ["build", "dist", "node_modules"], - "include": [ - "test/**/*.ts" - ], - "files": [ - "src/index.ts" - ] -} diff --git a/packages/live-share-turbo/typedoc.json b/packages/live-share-turbo/typedoc.json deleted file mode 100644 index 3facbaf81..000000000 --- a/packages/live-share-turbo/typedoc.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "entryPoints": ["./src/index.ts"], - "excludeExternals": true, - "excludePrivate": true, - "excludeInternal": true, - "name": "_microsoft_live_share_turbo", - "validation": { - "invalidLink": true - } -} diff --git a/packages/live-share-turbo/src/test/.mocharc.js b/packages/live-share/.mocharc.cjs similarity index 96% rename from packages/live-share-turbo/src/test/.mocharc.js rename to packages/live-share/.mocharc.cjs index 28b840eb9..49a4dd356 100644 --- a/packages/live-share-turbo/src/test/.mocharc.js +++ b/packages/live-share/.mocharc.cjs @@ -3,7 +3,7 @@ * Licensed under the Microsoft Live Share SDK License. */ -'use strict'; +"use strict"; const packageDir = `${__dirname}/../..`; diff --git a/packages/live-share/.nycrc.json b/packages/live-share/.nycrc.json index cc236d58b..ec2ba788b 100644 --- a/packages/live-share/.nycrc.json +++ b/packages/live-share/.nycrc.json @@ -8,4 +8,4 @@ "branches": 90, "functions": 95, "lines": 90 - } \ No newline at end of file +} diff --git a/packages/live-share/README.md b/packages/live-share/README.md index 9b635c3ad..6cd63dd6f 100644 --- a/packages/live-share/README.md +++ b/packages/live-share/README.md @@ -42,18 +42,10 @@ import { app, LiveShareHost } from "@microsoft/teams-js"; // Initialize Teams Client SDK await app.initialize(); -// Define Fluid schema -const schema = { - // Your initial SharedObject for your app - initialObjects: { - exampleMap: SharedMap, - ..., - }, -}; // create space based on Teams context const host = LiveShareHost.create(); const client = new LiveShareClient(host); -const { container } = await client.joinContainer(schema); +await client.join(); ... // listen to and send events on container.initialObjects. @@ -84,9 +76,10 @@ The Live Share SDK contains dependencies for [@microsoft/teams-js](https://www.n **It is critical that your app use the package dependencies listed in the table below.** Lookup the version of the `@microsoft/live-share` you're using and set any other dependencies in your package.json file to match: -| @microsoft/live-share | @microsoft/teams-js | fluid-framework | @microsoft/live-share-\* | @fluidframework/azure-client | @microsoft/TeamsFx | @microsoft/TeamsFx-react | -| --------------------- | -------------------- | --------------- | -------------------------- | ---------------------------- | ------------------------------- | ------------------------------- | -| ^1.0.0 | ^2.11.0 | ^1.2.3 | ^1.0.0 | ^1.0.0 | ^2.5.0 | ^2.5.0 | +| @microsoft/live-share | @microsoft/teams-js | fluid-framework | @microsoft/live-share-\* | @fluidframework/azure-client | @microsoft/TeamsFx | @microsoft/TeamsFx-react | +| --------------------- | ------------------- | --------------- | ------------------------ | ---------------------------- | ------------------ | ------------------------ | +| ^2.0.0 | ^2.11.0 | ^2.0.0 | ^2.0.0 | ^2.0.0 | ^2.5.0 | ^2.5.0 | +| ^1.0.0 | ^2.11.0 | ^1.2.3 | ^1.0.0 | ^1.0.0 | ^2.5.0 | ^2.5.0 | ## Contributing diff --git a/packages/live-share/internal.d.ts b/packages/live-share/internal.d.ts new file mode 100644 index 000000000..f1e0ebe42 --- /dev/null +++ b/packages/live-share/internal.d.ts @@ -0,0 +1,2 @@ +// This file provides resolution of "@microsoft/live-share/internal" for node10 +export * from "./bin/esm/index.internal"; diff --git a/packages/live-share/package.json b/packages/live-share/package.json index 33df6d7ec..1e06e1544 100644 --- a/packages/live-share/package.json +++ b/packages/live-share/package.json @@ -1,41 +1,61 @@ { "name": "@microsoft/live-share", - "version": "1.4.0", + "version": "2.0.0-internal.18", "description": "Building collaborative experiences for Microsoft Teams and M365 using Fluid.", "author": "Microsoft", "license": "SEE LICENSE IN LICENSE", - "main": "./bin/index.js", - "types": "./bin/index.d.ts", + "type": "module", "scripts": { "clean": "npx shx rm -rf bin", - "build": "tsc -p tsconfig.build.json", - "test": "ts-mocha --config ./src/test/.mocharc.js src --recursive --extension .spec.ts --timeout 10000", - "test:debug": "ts-mocha --config ./src/test/.mocharc.js src --recursive --extension .spec.ts --inspect-brk", + "build": "node ../../internal/build-tools/build-package.js --esm", + "build:test": "node ../../internal/build-tools/build-package.js --test", + "test": "npm run build:test && start-server-and-test test:client:start:server 7070 test:run", + "test:run": "mocha --config .mocharc.cjs --recursive \"./bin/test/**/*.spec.js\" --timeout 10000", + "test:debug": "npm run build:test && mocha --config .mocharc.cjs --recursive \"./bin/test/**/*.spec.js\" --inspect-brk", "test:coverage": "nyc --reporter=html --reporter=text --reporter=text-summary npm test", - "test:race": "node test-for-race-conditions.js" + "test:race": "npm run build:test && start-server-and-test test:client:start:server 7070 test:race:run", + "test:race:run": "node test-for-race-conditions.js", + "test:client:start:server": "npx tinylicious@latest > tinylicious.log 2>&1" + }, + "scriptsComments": { + "test": "does additional local server setup that LiveShareClient.spec.ts and AzureLiveShareClient.spec.ts need, then runs all tests with test:run" + }, + "exports": { + "./package.json": "./package.json", + ".": { + "import": "./bin/esm/index.public.js" + }, + "./internal": { + "import": "./bin/esm/index.internal.js" + } }, "dependencies": { + "@fluid-internal/client-utils": ">=2.40 <2.120", + "@fluidframework/aqueduct": ">=2.40 <2.120", + "@fluidframework/core-interfaces": ">=2.40 <2.120", + "@fluidframework/core-utils": ">=2.40 <2.120", + "@fluidframework/register-collection": ">=2.40 <2.120", "uuid": "^9.0.0" }, "devDependencies": { - "@fluidframework/azure-client": "^1.1.1", - "@fluidframework/test-client-utils": "^1.3.6", - "@fluidframework/test-runtime-utils": "^1.3.6", - "@fluidframework/test-utils": "^1.3.6", - "@fluidframework/test-version-utils": "^1.3.6", + "@fluidframework/mocha-test-setup": "^2.0.0-rc.1.0.9", + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", + "@fluidframework/test-utils": ">=2.40 <2.120", + "@live-share-private/test-utils": "^1.0.0", "@types/assert": "^1.5.6", "@types/mocha": "^10.0.1", "@types/node": "^20.2.3", "@types/uuid": "9.0.1", - "fluid-framework": "^1.3.6", + "fluid-framework": ">=2.40 <2.120", "mocha": "^10.2.0", "nyc": "^15.1.0", + "start-server-and-test": "^2.0.4", "ts-mocha": "^10.0.0", - "typescript": "^5.0.4" + "typescript": "~5.5.3" }, "peerDependencies": { - "@fluidframework/azure-client": "^1.0.0", - "fluid-framework": "^1.2.3" + "@fluidframework/azure-client": ">=2.40 <2.120", + "fluid-framework": ">=2.40 <2.120" }, "repository": { "directory": "packages/live-share", diff --git a/packages/live-share/src/AzureLiveShareClient.ts b/packages/live-share/src/AzureLiveShareClient.ts new file mode 100644 index 000000000..2173a9dfb --- /dev/null +++ b/packages/live-share/src/AzureLiveShareClient.ts @@ -0,0 +1,149 @@ +/*! + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Microsoft Live Share SDK License. + */ + +import { ContainerSchema, IFluidContainer } from "fluid-framework"; +import { + AzureClient, + AzureClientProps, + AzureContainerServices, +} from "@fluidframework/azure-client"; +import { BaseLiveShareClient } from "./internals/BaseLiveShareClient.js"; +import { ILiveShareHost } from "./interfaces.js"; +import { AzureLiveShareHost } from "./AzureLiveShareHost.js"; +import { LiveShareRuntime } from "./internals/LiveShareRuntime.js"; +import { getLiveContainerSchema } from "./internals/schema-injection-utils.js"; +import { LiveShareClient } from "./LiveShareClient.js"; +import { LiveDataObject } from "./internals/LiveDataObject.js"; +import { FluidCompatibilityMode } from "./internals/consts.js"; + +/** + * @alpha + * The `AzureLiveShareClient` implementation `BaseLiveShareClient`. + * @see BaseLiveShareClient + * + * @remarks + * You may choose to use this instead of {@link LiveShareClient} if you are using a custom Azure Fluid Relay instance. + * {@link LiveShareClient} does support custom Azure Fluid Relay connections, but only allows joining a container via {@link LiveShareClient.join}. + * Use {@link AzureLiveShareClient.getContainer} and {@link AzureLiveShareClient.createContainer} for more fine-grained control of connecting to containers. + * This ensures you can still use {@link LiveDataObject} DDS's, and useful Live Share features like {@link BaseLiveShareClient.getDDS}. + */ +export class AzureLiveShareClient extends BaseLiveShareClient { + private _host: ILiveShareHost; + private _client: AzureClient; + private _results: + | { + container: IFluidContainer; + services: AzureContainerServices; + } + | undefined; + + /** + * @hidden + */ + protected getDDSErrorJoinFunctionText: string = + "getContainer or createContainer"; + + /** + * Creates a new client instance using configuration parameters. + * @param props - Properties for initializing a new AzureClient instance + * @param host Optional. ILiveShareHost implementation to use when using Live Share DDS's. + */ + constructor( + props: AzureClientProps, + host: ILiveShareHost = AzureLiveShareHost.create(true) + ) { + super(new LiveShareRuntime(host)); + this._client = new AzureClient(props); + this._host = host; + } + + /** + * See {@link BaseLiveShareClient.results} for more information. + */ + public get results(): + | { + container: IFluidContainer; + services: AzureContainerServices; + } + | undefined { + return this._results; + } + + /** + * Creates a new detached container instance in the Azure Fluid Relay. + * + * @remarks + * Internally uses `AzureClient.createContainer`. + * See the docs for `AzureClient.createContainer` for more information. + * {@link https://fluidframework.com/docs/api/v2/azure-client/azureclient-class#createcontainer-method} + * + * @param initialObjects Optional. Fluid ContainerSchema initialObjects. + * @returns New detached container instance along with associated services. + */ + public async createContainer( + fluidContainerSchema?: T + ): Promise<{ + container: IFluidContainer; + services: AzureContainerServices; + }> { + const schema = this.getInjectedContainerSchema(fluidContainerSchema); + const results = (this._results = await this._client.createContainer( + schema, + FluidCompatibilityMode + )); + if (this._host instanceof AzureLiveShareHost) { + this._host.setAudience(this._results.services.audience); + } + + await this.addTurboFolder(this._results.container); + + await this._runtime.start(); + return results; + } + + /** + * Accesses the existing container given its unique ID in the Azure Fluid Relay. + * + * @remarks + * Internally uses `AzureClient.getContainer`. + * See the docs for `AzureClient.getContainer` for more information. + * {@link https://fluidframework.com/docs/api/v2/azure-client/azureclient-class#getcontainer-method} + * + * @param id - Unique ID of the container in Azure Fluid Relay. + * @param initialObjects Optional. Fluid ContainerSchema initialObjects. + * @param host Optional. ILiveShareHost implementation to use when using Live Share DDS's. + * @returns Existing container instance along with associated services. + */ + public async getContainer< + TContainerSchema extends ContainerSchema = ContainerSchema, + >( + id: string, + fluidContainerSchema?: TContainerSchema + ): Promise<{ + container: IFluidContainer; + services: AzureContainerServices; + }> { + const schema = this.getInjectedContainerSchema(fluidContainerSchema); + const results = (this._results = await this._client.getContainer( + id, + schema, + FluidCompatibilityMode + )); + if (this._host instanceof AzureLiveShareHost) { + this._host.setAudience(this._results.services.audience); + } + await this._runtime.start(); + return results; + } + + private getInjectedContainerSchema< + TContainerSchema extends ContainerSchema, + >(fluidContainerSchema?: TContainerSchema): TContainerSchema { + return getLiveContainerSchema( + this.getContainerSchema(fluidContainerSchema), + this._runtime + ); + } +} diff --git a/packages/live-share/src/AzureLiveShareHost.ts b/packages/live-share/src/AzureLiveShareHost.ts index ea91a0cf9..c7cace839 100644 --- a/packages/live-share/src/AzureLiveShareHost.ts +++ b/packages/live-share/src/AzureLiveShareHost.ts @@ -6,8 +6,8 @@ import { ILiveShareHost, INtpTimeInfo, UserMeetingRole, -} from "./interfaces"; -import { Deferred } from "./internals"; +} from "./interfaces.js"; +import { Deferred } from "./internals/Deferred.js"; /** * @alpha @@ -73,9 +73,9 @@ export class AzureLiveShareHost implements ILiveShareHost { ); } return { - userId: audienceInfo.userId, + userId: audienceInfo.id, roles: this.getRolesForAudienceMember(audienceInfo), - displayName: audienceInfo.userName, + displayName: audienceInfo.name, }; } diff --git a/packages/live-share/src/HostTimestampProvider.ts b/packages/live-share/src/HostTimestampProvider.ts index 34cb61b67..1c7aca707 100644 --- a/packages/live-share/src/HostTimestampProvider.ts +++ b/packages/live-share/src/HostTimestampProvider.ts @@ -3,8 +3,8 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { TimestampProvider } from "./TimestampProvider"; -import { ILiveShareHost, INtpTimeInfo } from "./interfaces"; +import { TimestampProvider } from "./TimestampProvider.js"; +import { ILiveShareHost, INtpTimeInfo } from "./interfaces.js"; /** * Timestamp Provider that calls the Live Share Host to lookup the current time. diff --git a/packages/live-share/src/LiveEvent.ts b/packages/live-share/src/LiveEvent.ts index 1fb9c9533..cbf809d10 100644 --- a/packages/live-share/src/LiveEvent.ts +++ b/packages/live-share/src/LiveEvent.ts @@ -3,24 +3,24 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { DataObjectFactory } from "@fluidframework/aqueduct"; -import { IEvent } from "@fluidframework/common-definitions"; +import { DataObjectFactory } from "@fluidframework/aqueduct/legacy"; +import { IEvent } from "@fluidframework/core-interfaces"; import { UserMeetingRole, - IClientTimestamp, ILiveEvent, LiveDataObjectInitializeState, -} from "./interfaces"; -import { LiveEventScope } from "./LiveEventScope"; -import { LiveEventTarget } from "./LiveEventTarget"; -import { DynamicObjectRegistry } from "./DynamicObjectRegistry"; -import { LiveDataObject } from "./LiveDataObject"; -import { cloneValue } from "./internals"; +} from "./interfaces.js"; +import { LiveEventScope } from "./internals/LiveEventScope.js"; +import { LiveEventTarget } from "./internals/LiveEventTarget.js"; +import { DynamicObjectRegistry } from "./internals/DynamicObjectRegistry.js"; +import { LiveDataObject } from "./internals/LiveDataObject.js"; import { LiveDataObjectInitializeNotNeededError, LiveDataObjectNotInitializedError, UnexpectedError, -} from "./errors"; +} from "./errors.js"; +import { SharedObjectKind } from "fluid-framework"; +import { cloneValue } from "./internals/utils.js"; /** * Events supported by `LiveEvent` object. @@ -68,7 +68,7 @@ export interface ILiveEventEvents extends IEvent { * `LiveEvents`. Use something like the `LiveState` class when syncing state. * @template TEvent Type of event to broadcast. */ -export class LiveEvent extends LiveDataObject<{ +export class LiveEventClass extends LiveDataObject<{ Events: ILiveEventEvents; }> { private _eventTarget?: LiveEventTarget; @@ -82,8 +82,8 @@ export class LiveEvent extends LiveDataObject<{ * The objects fluid type factory. */ public static readonly factory = new DataObjectFactory( - LiveEvent.TypeName, - LiveEvent, + LiveEventClass.TypeName, + LiveEventClass, [], {} ); @@ -100,6 +100,30 @@ export class LiveEvent extends LiveDataObject<{ * @returns a void promise that resolves once complete. * * @throws error when `.initialize()` has already been called for this class instance. + * + * @example + ```ts + import { LiveShareClient, LiveEvent } from "@microsoft/live-share"; + import { LiveShareHost } from "@microsoft/teams-js"; + + + // Join the Fluid container and create LiveEvent instance + const host = LiveShareHost.create(); + const client = new LiveShareClient(host); + await client.join(); + const messages = await client.getDDS("unique-id", LiveEvent); + + // Register listener to receive events sent through this object. + messages.on("received", async (event: string, local: boolean, clientId: string) => { + console.log("Received message:", event, "from clientId", clientId); + }); + + // Initialize LiveEvent + await messages.initialize(); + + // Can now safely send events + await messages.send("Hello world"); + ``` */ public initialize(allowedRoles?: UserMeetingRole[]): Promise { LiveDataObjectInitializeNotNeededError.assert( @@ -140,14 +164,48 @@ export class LiveEvent extends LiveDataObject<{ * The event will be queued for delivery if the client isn't currently connected. * * @param evt Event to send. If omitted, an event will still be sent but it won't include any custom event data. + * @param targetClientId Optional. When specified, the signal is only sent to the provided client id. * * @returns A promise with the full event object that was sent, including the timestamp of when the event was sent and the clientId if known. * The clientId will be `undefined` if the client is disconnected at time of delivery. * * @throws error if initialization has not yet succeeded. * @throws error if the local user does not have the required roles defined through the `allowedRoles` prop in `.initialize()`. + * + * @example + ```ts + import { LiveShareClient, LiveEvent } from "@microsoft/live-share"; + import { LiveShareHost } from "@microsoft/teams-js"; + + // Declare interface for type of custom data for user + interface ICustomReaction { + emoji: string; + forUserId: string; + } + + // Join the Fluid container and create LiveEvent instance + const host = LiveShareHost.create(); + const client = new LiveShareClient(host); + await client.join(); + const reactions = await client.getDDS("unique-id", LiveEvent); + + // Register listener to receive events sent through this object. + reactions.on("received", async (event: ICustomReaction, local: boolean, clientId: string) => { + console.log("Received reaction:", event, "from clientId", clientId); + }); + + // Initialize LiveEvent prior to sending event + await reactions.initialize(); + await reactions.send({ + emoji: "❤️", + forUserId: "SOME_OTHER_USER_ID", + }); + ``` */ - public async send(evt: TEvent): Promise> { + public async send( + evt: TEvent, + targetClientId?: string + ): Promise> { LiveDataObjectNotInitializedError.assert( "LiveEvent:send", "send", @@ -159,69 +217,27 @@ export class LiveEvent extends LiveDataObject<{ "`this._eventTarget` is undefined, implying there was an error during initialization that should not occur." ); - return await this._eventTarget.sendEvent(evt); + return await this._eventTarget.sendEvent(evt, targetClientId); } /** - * Returns true if a received event is newer then the current event. - * - * @remarks - * Used when building new Live objects to process state change events. The `isNewer()` - * method implements an algorithm that deals with conflicting events that have the same timestamp - * and older events that should have debounced the current event. - * - * - When the received event has the same timestamp as the current event, each events clientId - * will be used as a tie breaker. The clientId containing the lower sort order wins any ties. - * - Older events are generally ignored unless a debounce period is specified. An older event - * that should have debounced the current event will be considered newer. - * - * The algorithm employed by isNewer() helps ensure that all clients will eventually reach a - * consistent state with one other. - * @param current Current event to compare received event against. - * @param received Received event. - * @param debouncePeriod Optional. Time in milliseconds to ignore any new events for. Defaults to 0 ms. - * @returns True if the received event is newer then the current event and should replace the current one. + * initializingFirstTime is run only once by the first client to create the DataObject. Here we use it to + * initialize the state of the DataObject. */ - public static isNewer( - current: IClientTimestamp | undefined, - received: IClientTimestamp, - debouncePeriod = 0 - ): boolean { - if (current) { - if (current.timestamp == received.timestamp) { - // In a case where both clientId's are blank that's the local client in a disconnected state - const cmp = (current.clientId || "").localeCompare( - received.clientId || "" - ); - if (cmp <= 0) { - // - cmp == 0 is same user. We use to identify events for same user as newer but - // that was causing us to fire duplicate state & presence change events. The better - // approach is to update the timestamp provider to never return the same timestamp - // twice. (Comparison was changed on 8/2/2022) - // - cmp > 0 is a tie breaker so we'll take that event as well (comparing 'a' with 'c' - // will result in a negative value). - return false; - } - } else if (current.timestamp > received.timestamp) { - // Did we receive an older event that should have caused us to debounce the current one? - const delta = current.timestamp - received.timestamp; - if (delta > debouncePeriod) { - return false; - } - } else { - // Is the new event within the debounce period? - const delta = received.timestamp - current.timestamp; - if (delta < debouncePeriod) { - return false; - } - } - } - - return true; + protected async initializingFirstTime() { + this.debugInfo = `LivePresence-${this.id}`; } } +export type LiveEvent = LiveEventClass; + +// eslint-disable-next-line no-redeclare +export const LiveEvent = (() => { + const kind = LiveEventClass; + return kind as typeof kind & SharedObjectKind; +})(); + /** - * Register `LiveEvent` as an available `LoadableObjectClass` for use in packages that support dynamic object loading, such as `@microsoft/live-share-turbo`. + * Register `LiveEvent` as an available `SharedObjectKind` for use in dynamic object loading. */ DynamicObjectRegistry.registerObjectClass(LiveEvent, LiveEvent.TypeName); diff --git a/packages/live-share/src/LiveEventTimer.ts b/packages/live-share/src/LiveEventTimer.ts deleted file mode 100644 index 72359eaea..000000000 --- a/packages/live-share/src/LiveEventTimer.ts +++ /dev/null @@ -1,117 +0,0 @@ -/*! - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Microsoft Live Share SDK License. - */ - -import { TimeInterval } from "./TimeInterval"; -import { LiveEventSource } from "./LiveEventSource"; -import { ILiveEvent } from "./interfaces"; - -/** - * Periodically broadcasts an event to listening `LiveEventTarget` instances. - */ -export class LiveEventTimer { - private _eventSource: LiveEventSource; - private _createEvent: () => T; - private _delay: TimeInterval; - private _isRunning = false; - private _timer?: any; - - /** - * Creates a new `LiveEventTimer instance. - * @param eventSource Event source that will be used to emit events. - * @param createEvent Function used to construct an event to send. This will be called at regular intervals prior to sending an event. - * @param delay Period to delay for in milliseconds. - * @param repeat Optional. If true the timer will repeat once `start` is called, otherwise a single event will be sent after the delay. Defaults to false. - */ - constructor( - eventSource: LiveEventSource, - createEvent: () => T, - delay: number, - repeat = false - ) { - this._eventSource = eventSource; - this._createEvent = createEvent; - this._delay = new TimeInterval(delay); - this.repeat = repeat; - } - - /** - * The rate at which the events are sent in milliseconds. - */ - public get delay(): number { - return this._delay.milliseconds; - } - - public set delay(value: number) { - this._delay.milliseconds = value; - } - - /** - * Returns true if the timer is currently running. - */ - public get isRunning(): boolean { - return this._isRunning; - } - - /** - * If true the event will automatically repeat at an interval specified by the `delay`. - */ - public repeat: boolean; - - /** - * Immediately sends an event. - * - * @remarks - * The `createEvent` callback to construct the event is called but does not impact any pending - * timeouts. Call `start` after calling `sendEvent` if you'd like to skip the next timer - * interval. - */ - public sendEvent(): Promise> { - const evt = this._createEvent(); - return this._eventSource.sendEvent(evt); - } - - /** - * Starts the timer. - * - * @remarks - * If the timer is running it will be stooped and then re-started with a new `delay`. - */ - public start(): void { - this.stop(); - this._isRunning = true; - this.delayedEmit(this.delay); - } - - /** - * Stops the timer if its running. - */ - public stop(): void { - if (this._timer != undefined) { - clearTimeout(this._timer); - this._timer = undefined; - } - this._isRunning = false; - } - - private delayedEmit(delay: number): void { - this._timer = setTimeout(() => { - this._timer = undefined; - const startedAt = new Date().getTime(); - this.sendEvent().catch((err) => { - console.warn(err); - }); - - // Auto-repeat - if (this._isRunning && this.repeat) { - // We want to send an every ${this.delay} milliseconds so we subtract the duration - // of the time it took us to emit the event. If it took longer then ${this.delay} - // we will skip to the next interval (hence the %mod% operation.) - const duration = - (new Date().getTime() - startedAt) % this.delay; - this.delayedEmit(this.delay - duration); - } - }, delay); - } -} diff --git a/packages/live-share/src/LiveFollowMode.ts b/packages/live-share/src/LiveFollowMode.ts index 76ed7210b..063edfd1b 100644 --- a/packages/live-share/src/LiveFollowMode.ts +++ b/packages/live-share/src/LiveFollowMode.ts @@ -1,18 +1,21 @@ -import { LiveDataObject } from "./LiveDataObject"; -import { LiveState } from "./LiveState"; -import { ILivePresenceEvents, LivePresence } from "./LivePresence"; -import { DataObjectFactory } from "@fluidframework/aqueduct"; +import { LiveDataObject } from "./internals/LiveDataObject.js"; +import { LiveState } from "./LiveState.js"; +import { ILivePresenceEvents, LivePresence } from "./LivePresence.js"; +import { DataObjectFactory } from "@fluidframework/aqueduct/legacy"; import { IFluidHandle } from "@fluidframework/core-interfaces"; -import { assert } from "@fluidframework/common-utils"; -import { LiveDataObjectInitializeState, UserMeetingRole } from "./interfaces"; -import { LiveTelemetryLogger } from "./LiveTelemetryLogger"; -import { LivePresenceUser, PresenceState } from "./LivePresenceUser"; -import { DynamicObjectRegistry } from "./DynamicObjectRegistry"; +import { + LiveDataObjectInitializeState, + UserMeetingRole, +} from "./interfaces.js"; +import { LiveTelemetryLogger } from "./LiveTelemetryLogger.js"; +import { LivePresenceUser, PresenceStatus } from "./LivePresenceUser.js"; +import { DynamicObjectRegistry } from "./internals/DynamicObjectRegistry.js"; import { LiveDataObjectInitializeNotNeededError, LiveDataObjectNotInitializedError, UnexpectedError, -} from "./errors"; +} from "./errors.js"; +import { SharedObjectKind } from "fluid-framework"; /** * Events supported by `LiveFollowMode` object. @@ -32,8 +35,9 @@ export enum LiveFollowModeEvents { * Event typings for `LiveFollowMode` class. * @template TData Type of data object to share with clients. */ -export interface ILiveFollowModeEvents - extends ILivePresenceEvents> { +export interface ILiveFollowModeEvents extends ILivePresenceEvents< + IFollowModePresenceUserData +> { /** * The presence information for the local or a remote user has changed. * @param event Name of event. @@ -172,7 +176,7 @@ const livePresenceKey = "@microsoft/live-share:LiveFollowMode:LivePresence"; * * @template TData Type of data value to share with clients for each user (e.g., the user's camera position in a 3D scene). */ -export class LiveFollowMode extends LiveDataObject<{ +export class LiveFollowModeClass extends LiveDataObject<{ Events: ILiveFollowModeEvents; }> { private _logger?: LiveTelemetryLogger; @@ -203,8 +207,8 @@ export class LiveFollowMode extends LiveDataObject<{ * The objects fluid type factory. */ public static readonly factory = new DataObjectFactory( - LiveFollowMode.TypeName, - LiveFollowMode, + LiveFollowModeClass.TypeName, + LiveFollowModeClass, [], {}, new Map>([ @@ -230,7 +234,7 @@ export class LiveFollowMode extends LiveDataObject<{ if (presentingUser && presentingUser.data) { // Count is all online users minus the presenting user const otherUsersCount = - this.getUsers(PresenceState.online).length - 1; + this.getUsers(PresenceStatus.online).length - 1; if (presentingUser.isLocalUser) { // The local user is the presenter return { @@ -268,7 +272,7 @@ export class LiveFollowMode extends LiveDataObject<{ const otherUsersCount = this.getUserFollowers( followingUser.userId, - PresenceState.online + PresenceStatus.online ).length - 1; if (this._suspended) { // Local user is following specific user but is suspended @@ -292,7 +296,7 @@ export class LiveFollowMode extends LiveDataObject<{ const userCountFollowingLocalUser = this.getUserFollowers( localUser.userId, - PresenceState.online + PresenceStatus.online ).length; if (userCountFollowingLocalUser > 0) { // User is being followed by other users @@ -311,7 +315,7 @@ export class LiveFollowMode extends LiveDataObject<{ type: FollowModeType.local, otherUsersCount: this.getUserFollowers( localUser.userId, - PresenceState.online + PresenceStatus.online ).length, isLocalValue: true, }; @@ -343,14 +347,18 @@ export class LiveFollowMode extends LiveDataObject<{ * never be undefined after `initializingFirstTime`. */ private get presence() { - assert(this._presence !== undefined, "_presence not initialized"); + UnexpectedError.assert( + this._presence !== undefined, + "LiveFollowMode:presence", + "presence is undefined" + ); return this._presence; } /** * Initialize the object to begin sending/receiving state updates through this DDS. * - * @param initialState Initial state value + * @param initialUserStateValue Initial state value for the local user * @param allowedRoles Optional. List of roles allowed to make state changes. * * @returns a void promise that resolves once complete @@ -358,9 +366,42 @@ export class LiveFollowMode extends LiveDataObject<{ * @throws error when `.initialize()` has already been called for this class instance. * @throws fatal error when `.initialize()` has already been called for an object of same id but with a different class instance. * This is most common when using dynamic objects through Fluid. + * + * @example + ```ts + import { + LiveShareClient, + LiveFollowMode, + IFollowModeState, + FollowModePresenceUser, + } from "@microsoft/live-share"; + import { LiveShareHost } from "@microsoft/teams-js"; + + // Join the Fluid container and create the LivePresence instance + const host = LiveShareHost.create(); + const client = new LiveShareClient(host); + await client.join(); + const followCursors = await client.getDDS("unique-id", LiveFollowMode); + + // Listen for changes to presence & state prior to calling initialize + followCursors.on("presenceChanged", async (user: FollowModePresenceUser, local: boolean) => { + // Update UI to reflect new user value + }); + followCursors.on("stateChanged", async (state: IFollowModeState, local: boolean) => { + // Update UI to reflect new state + }); + // Initialize LivePresence with initial presence data for local user + await followCursors.initialize(0); + + // Update local user's cursor position when they select new text position in editor + await followCursors.update(1); + + // Start presenting to other users + await followCursors.startPresenting(); + ``` */ public async initialize( - initialState: TData, + initialUserStateValue: TData, allowedRoles?: UserMeetingRole[] ): Promise { LiveDataObjectInitializeNotNeededError.assert( @@ -388,7 +429,7 @@ export class LiveFollowMode extends LiveDataObject<{ await Promise.all([ this.presentingUserIdState.initialize(undefined, allowedRoles), this.presence.initialize({ - stateValue: initialState, + stateValue: initialUserStateValue, followingUserId: undefined, }), ]); @@ -415,6 +456,36 @@ export class LiveFollowMode extends LiveDataObject<{ * @returns a void promise that resolves once the update event has been sent to the server. * * @throws error if initialization has not yet succeeded. + * + * @example + ```ts + import { + LiveShareClient, + LiveFollowMode, + IFollowModeState, + FollowModePresenceUser, + } from "@microsoft/live-share"; + import { LiveShareHost } from "@microsoft/teams-js"; + + // Join the Fluid container and create the LivePresence instance + const host = LiveShareHost.create(); + const client = new LiveShareClient(host); + await client.join(); + const followCursors = await client.getDDS("unique-id", LiveFollowMode); + + // Listen for changes to presence & state prior to calling initialize + followCursors.on("presenceChanged", async (user: FollowModePresenceUser, local: boolean) => { + // Update UI to reflect new user value + }); + followCursors.on("stateChanged", async (state: IFollowModeState, local: boolean) => { + // Update UI to reflect new state + }); + // Initialize LivePresence with initial presence data for local user + await followCursors.initialize(0); + + // Update local user's cursor position when they select new text position in editor + await followCursors.update(1); + ``` */ public async update(newValue: TData): Promise { LiveDataObjectNotInitializedError.assert( @@ -448,6 +519,40 @@ export class LiveFollowMode extends LiveDataObject<{ * @throws error if initialization has not yet succeeded. * @throws error if the local user is already the presenter. * @throws error if the local user does not have the required roles to present. + * + * @example + ```ts + import { + LiveShareClient, + LiveFollowMode, + IFollowModeState, + FollowModePresenceUser, + } from "@microsoft/live-share"; + import { LiveShareHost } from "@microsoft/teams-js"; + + // Join the Fluid container and create the LivePresence instance + const host = LiveShareHost.create(); + const client = new LiveShareClient(host); + await client.join(); + const followCursors = await client.getDDS("unique-id", LiveFollowMode); + + // Listen for changes to presence & state prior to calling initialize + followCursors.on("presenceChanged", async (user: FollowModePresenceUser, local: boolean) => { + // Update UI to reflect new user value + }); + followCursors.on("stateChanged", async (state: IFollowModeState, local: boolean) => { + // Update UI to reflect new state + }); + // Initialize LivePresence with initial presence data for local user + await followCursors.initialize(0); + + // Start presenting to other users + await followCursors.startPresenting(); + + // Update local user's cursor position to broadcast to trigger "stateChanged" for all remote following clients. + // This is in addition to the "presenceChanged" that will be emitted. + await followCursors.update(1); + ``` */ public async startPresenting(): Promise { LiveDataObjectNotInitializedError.assert( @@ -482,6 +587,39 @@ export class LiveFollowMode extends LiveDataObject<{ * * @throws error if initialization has not yet succeeded. * @throws error if the local user does not have the required roles to stop presenting. + * + * @example + ```ts + import { + LiveShareClient, + LiveFollowMode, + IFollowModeState, + FollowModePresenceUser, + } from "@microsoft/live-share"; + import { LiveShareHost } from "@microsoft/teams-js"; + + // Join the Fluid container and create the LivePresence instance + const host = LiveShareHost.create(); + const client = new LiveShareClient(host); + await client.join(); + const followCursors = await client.getDDS("unique-id", LiveFollowMode); + + // Listen for changes to presence & state prior to calling initialize + followCursors.on("presenceChanged", async (user: FollowModePresenceUser, local: boolean) => { + // Update UI to reflect new user value + }); + followCursors.on("stateChanged", async (state: IFollowModeState, local: boolean) => { + // Update UI to reflect new state + }); + // Initialize LivePresence with initial presence data for local user + await followCursors.initialize(0); + + // Start presenting to other users + await followCursors.startPresenting(); + + // Stop presenting to other users + await followCursors.stopPresenting(); + ``` */ public async stopPresenting(): Promise { LiveDataObjectNotInitializedError.assert( @@ -504,6 +642,44 @@ export class LiveFollowMode extends LiveDataObject<{ * @returns a void promise once the operation succeeds. * * @throws error if initialization has not yet succeeded. + * + * @example + ```ts + import { + LiveShareClient, + LiveFollowMode, + IFollowModeState, + FollowModePresenceUser, + FollowModeType, + } from "@microsoft/live-share"; + import { LiveShareHost } from "@microsoft/teams-js"; + + // Join the Fluid container and create the LivePresence instance + const host = LiveShareHost.create(); + const client = new LiveShareClient(host); + await client.join(); + const followCursors = await client.getDDS("unique-id", LiveFollowMode); + + // Listen for changes to presence & state prior to calling initialize + followCursors.on("presenceChanged", async (user: FollowModePresenceUser, local: boolean) => { + // Update UI to reflect new user value + }); + followCursors.on("stateChanged", async (state: IFollowModeState, local: boolean) => { + // Update UI to reflect new state + }); + // Initialize LivePresence with initial presence data for local user + await followCursors.initialize(0); + + // Example function that would be applied whenever the local user changes their text cursor in an editor + async function onTextEditorPositionChanged(newPosition: number) { + await followCursors.update(newPosition); + // If following another user/presenter, suspend following since the user changed to their own position + if ([FollowModeType.followPresenter, FollowModeType.followUser].includes(followCursors.state.type)) { + await followCursors.beginSuspension(); + // TODO: update UI with a "Sync to presenter" button + } + } + ``` */ public async beginSuspension(): Promise { LiveDataObjectNotInitializedError.assert( @@ -526,6 +702,41 @@ export class LiveFollowMode extends LiveDataObject<{ * @returns a void promise once the operation succeeds. * * @throws error if initialization has not yet succeeded. + * + * @example + ```ts + import { + LiveShareClient, + LiveFollowMode, + IFollowModeState, + FollowModePresenceUser, + } from "@microsoft/live-share"; + import { LiveShareHost } from "@microsoft/teams-js"; + + // Join the Fluid container and create the LivePresence instance + const host = LiveShareHost.create(); + const client = new LiveShareClient(host); + await client.join(); + const followCursors = await client.getDDS("unique-id", LiveFollowMode); + + // Listen for changes to presence & state prior to calling initialize + followCursors.on("presenceChanged", async (user: FollowModePresenceUser, local: boolean) => { + // Update UI to reflect new user value + }); + followCursors.on("stateChanged", async (state: IFollowModeState, local: boolean) => { + // Update UI to reflect new state + }); + // Initialize LivePresence with initial presence data for local user + await followCursors.initialize(0); + + // Start suspension + await followCursors.beginSuspension(); + + // Example function for when a suspended user clicks "Sync to presenter" in your app + async function onClickSyncToPresenter() { + await followCursors.endSuspension(); + } + ``` */ public async endSuspension(): Promise { LiveDataObjectNotInitializedError.assert( @@ -555,6 +766,38 @@ export class LiveFollowMode extends LiveDataObject<{ * @throws error if initialization has not yet succeeded. * @throws error if attempting to follow a user that is not recognized by this object's `LivePresence` instance. * @throws error if the `userId` provided is equal to the local user's `userId`. + * + * @example + ```ts + import { + LiveShareClient, + LiveFollowMode, + IFollowModeState, + FollowModePresenceUser, + } from "@microsoft/live-share"; + import { LiveShareHost } from "@microsoft/teams-js"; + + // Join the Fluid container and create the LivePresence instance + const host = LiveShareHost.create(); + const client = new LiveShareClient(host); + await client.join(); + const followCursors = await client.getDDS("unique-id", LiveFollowMode); + + // Listen for changes to presence & state prior to calling initialize + followCursors.on("presenceChanged", async (user: FollowModePresenceUser, local: boolean) => { + // Update UI to reflect new user value + }); + followCursors.on("stateChanged", async (state: IFollowModeState, local: boolean) => { + // Update UI to reflect new state + }); + // Initialize LivePresence with initial presence data for local user + await followCursors.initialize(0); + + // Example function that would be applied whenever the local user clicks on another user to follow + async function onClickFollowUser(user: FollowModePresenceUser) { + await followCursors.followUser(user.userId); + } + ``` */ public async followUser(userId: string): Promise { LiveDataObjectNotInitializedError.assert( @@ -592,6 +835,37 @@ export class LiveFollowMode extends LiveDataObject<{ * * @throws error if initialization has not yet succeeded. * @throws error if the user is not already following another user. + * + * @example + ```ts + import { + LiveShareClient, + LiveFollowMode, + IFollowModeState, + FollowModePresenceUser, + } from "@microsoft/live-share"; + import { LiveShareHost } from "@microsoft/teams-js"; + + // Join the Fluid container and create the LivePresence instance + const host = LiveShareHost.create(); + const client = new LiveShareClient(host); + await client.join(); + const followCursors = await client.getDDS("unique-id", LiveFollowMode); + + // Listen for changes to presence & state prior to calling initialize + followCursors.on("presenceChanged", async (user: FollowModePresenceUser, local: boolean) => { + // Update UI to reflect new user value + }); + followCursors.on("stateChanged", async (state: IFollowModeState, local: boolean) => { + // Update UI to reflect new state + }); + // Initialize LivePresence with initial presence data for local user + await followCursors.initialize(0); + + // Start and stop following a user + await followCursors.followUser("some-user-id"); + await followCursors.stopFollowing(); + ``` */ public async stopFollowing(): Promise { LiveDataObjectNotInitializedError.assert( @@ -621,7 +895,7 @@ export class LiveFollowMode extends LiveDataObject<{ * @param filter Optional. Presence state to filter enumeration to. * @returns Array of presence objects. */ - public getUsers(filter?: PresenceState): FollowModePresenceUser[] { + public getUsers(filter?: PresenceStatus): FollowModePresenceUser[] { return this.presence.getUsers(filter); } @@ -647,15 +921,54 @@ export class LiveFollowMode extends LiveDataObject<{ /** * Get the users that are following a given userId. + * + * @remarks + * Only includes users that called {@link followUser} for the given `userId`. + * Does not apply to cases where user called {@link startPresenting}. * * @param userId the userId of the person being followed. - * @param stateFilter the presence state to filter results by. + * @param statusFilter the presence state to filter results by. + * + * @example + ```ts + import { + LiveShareClient, + LiveFollowMode, + IFollowModeState, + FollowModePresenceUser, + PresenceStatus, + } from "@microsoft/live-share"; + import { LiveShareHost } from "@microsoft/teams-js"; + + // Join the Fluid container and create the LivePresence instance + const host = LiveShareHost.create(); + const client = new LiveShareClient(host); + await client.join(); + const followCursors = await client.getDDS("unique-id", LiveFollowMode); + + // Initialize LivePresence with initial presence data for local user + await followCursors.initialize(0); + + // Start following a user + await followCursors.followUser("some-user-id"); + + // Get all online users that are following that user. + // This list will include the local user. + const followers = await followCursors.getUserFollowers("some-user-id", PresenceStatus.online); + + // Stop following the user + await followCursors.stopFollowing(); + + // Get all users that are following that user. + // This list will NOT include the local user. + const allFollowers = await followCursors.getUserFollowers("some-user-id"); + ``` */ public getUserFollowers( userId: string, - stateFilter?: PresenceState + statusFilter?: PresenceStatus ): FollowModePresenceUser[] { - const users = this.getUsers(stateFilter); + const users = this.getUsers(statusFilter); return users.filter((user) => user.data?.followingUserId === userId); } @@ -673,6 +986,7 @@ export class LiveFollowMode extends LiveDataObject<{ * initialize the state of the DataObject. */ protected async initializingFirstTime() { + this.debugInfo = `LiveFollowMode-${this.id}`; // We create the live state instance const presentingUserIdLiveStatePromise = LiveState.factory.createChildInstance(this.context); @@ -732,8 +1046,16 @@ export class LiveFollowMode extends LiveDataObject<{ } } +export type LiveFollowMode = LiveFollowModeClass; + +// eslint-disable-next-line no-redeclare +export const LiveFollowMode = (() => { + const kind = LiveFollowModeClass; + return kind as typeof kind & SharedObjectKind; +})(); + /** - * Register `LiveFollowMode` as an available `LoadableObjectClass` for use in packages that support dynamic object loading, such as `@microsoft/live-share-turbo`. + * Register `LiveFollowMode` as an available `SharedObjectKind` for use in dynamic object loading. */ DynamicObjectRegistry.registerObjectClass( LiveFollowMode, diff --git a/packages/live-share/src/LivePresence.ts b/packages/live-share/src/LivePresence.ts index 7dc05ccf8..ca0c8dfcb 100644 --- a/packages/live-share/src/LivePresence.ts +++ b/packages/live-share/src/LivePresence.ts @@ -3,30 +3,44 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { DataObjectFactory } from "@fluidframework/aqueduct"; -import { IEvent } from "@fluidframework/common-definitions"; +import { DataObjectFactory } from "@fluidframework/aqueduct/legacy"; +import { IEvent } from "@fluidframework/core-interfaces"; import { LivePresenceUser, - PresenceState, + PresenceStatus, ILivePresenceEvent, LivePresenceReceivedEventData, -} from "./LivePresenceUser"; -import { LiveObjectSynchronizer } from "./LiveObjectSynchronizer"; -import { LiveTelemetryLogger } from "./LiveTelemetryLogger"; -import { cloneValue, TelemetryEvents } from "./internals"; +} from "./LivePresenceUser.js"; +import { LiveObjectSynchronizer } from "./internals/LiveObjectSynchronizer.js"; +import { LiveTelemetryLogger } from "./LiveTelemetryLogger.js"; import { LiveDataObjectInitializeNotNeededError, LiveDataObjectNotInitializedError, UnexpectedError, -} from "./errors"; -import { TimeInterval } from "./TimeInterval"; -import { DynamicObjectRegistry } from "./DynamicObjectRegistry"; +} from "./errors.js"; +import { TimeInterval } from "./TimeInterval.js"; +import { DynamicObjectRegistry } from "./internals/DynamicObjectRegistry.js"; import { IClientInfo, LiveDataObjectInitializeState, UserMeetingRole, -} from "./interfaces"; -import { LiveDataObject } from "./LiveDataObject"; +} from "./interfaces.js"; +import { LiveDataObject } from "./internals/LiveDataObject.js"; +import { SharedObjectKind } from "fluid-framework"; +import { cloneValue } from "./internals/utils.js"; +import { TelemetryEvents } from "./internals/consts.js"; +import { AzureMember } from "@fluidframework/azure-client"; + +/** + * Valid types of custom data for a {@link LivePresence} user. + */ +export type LivePresenceData = + | object + | string + | number + | boolean + | undefined + | null; /** * Events supported by `LivePresence` object. @@ -42,8 +56,9 @@ export enum LivePresenceEvents { * Event typings for `LivePresence` class. * @template TData Type of data object to share with clients. */ -export interface ILivePresenceEvents - extends IEvent { +export interface ILivePresenceEvents< + TData extends LivePresenceData = any, +> extends IEvent { /** * The presence information for the local or a remote user has changed. * @param event Name of event. @@ -64,17 +79,17 @@ export interface ILivePresenceEvents /** * Live fluid object that synchronizes presence information for the user with other clients. - * @template TData Type of data object to share with clients. + * @template TData Type of data object to share with clients. Can be any serializable JSON value. */ -export class LivePresence< - TData extends object = object +export class LivePresenceClass< + TData extends LivePresenceData = any, > extends LiveDataObject<{ Events: ILivePresenceEvents; }> { private _logger?: LiveTelemetryLogger; private _expirationPeriod = new TimeInterval(20000); private _users: LivePresenceUser[] = []; - private _lastEmitPresenceStateMap = new Map(); + private _lastEmitPresenceStateMap = new Map(); private _currentPresence?: LivePresenceReceivedEventData; private _synchronizer?: LiveObjectSynchronizer>; @@ -88,8 +103,8 @@ export class LivePresence< * The objects fluid type factory. */ public static readonly factory = new DataObjectFactory( - LivePresence.TypeName, - LivePresence, + LivePresenceClass.TypeName, + LivePresenceClass, [], {} ); @@ -124,8 +139,7 @@ export class LivePresence< /** * Initialize the object to begin sending/receiving presence updates through this DDS. * - * @param data Optional. Custom data object to share. A deep copy of the data object is saved to avoid any accidental modifications. - * @param state Optional. Initial presence state. Defaults to `PresenceState.online`. + * @param data Custom data object to share for local user. A deep copy of the data object is saved to avoid any accidental modifications. * @param allowedRoles Optional. List of roles allowed to emit presence changes. * * @returns a void promise that resolves once complete. @@ -133,10 +147,29 @@ export class LivePresence< * @throws error when `.initialize()` has already been called for this class instance. * @throws fatal error when `.initialize()` has already been called for an object of same id but with a different class instance. * This is most common when using dynamic objects through Fluid. + * @example + ```ts + import { LiveShareClient, LivePresence, LivePresenceUser } from "@microsoft/live-share"; + import { LiveShareHost } from "@microsoft/teams-js"; + + // Join the Fluid container and create the LivePresence instance + const host = LiveShareHost.create(); + const client = new LiveShareClient(host); + await client.join(); + const presence = await client.getDDS("unique-id", LivePresence); + + // Listen for changes to presence prior to calling initialize + presence.on("presenceChanged", async (user: LivePresenceUser, local: boolean) => { + console.log(user); + }); + // Initialize LivePresence with initial presence data for local user + await presence.initialize(true); + // Update presence after calling initialize + await presence.update(false); + ``` */ public async initialize( - data?: TData, - state = PresenceState.online, + data: TData, allowedRoles?: UserMeetingRole[] ): Promise { LiveDataObjectInitializeNotNeededError.assert( @@ -149,6 +182,9 @@ export class LivePresence< "LivePresence:initialize", "_synchronizer already set, which is an unexpected error." ); + + this.listenForAudienceMemberChanges(); + // Update initialize state as pending this.initializeState = LiveDataObjectInitializeState.pending; this._logger = new LiveTelemetryLogger(this.runtime, this.liveRuntime); @@ -162,7 +198,7 @@ export class LivePresence< name: "UpdatePresence", timestamp: 0, data: { - state, + status: PresenceStatus.online, data, }, }; @@ -172,14 +208,14 @@ export class LivePresence< ILivePresenceEvent >(this.id, this.runtime, this.liveRuntime); try { - await this._synchronizer!.start( - this._currentPresence!.data, - async (state, sender, local) => { + await this._synchronizer!.start({ + initialState: this._currentPresence!.data, + updateState: async (state, sender, local) => { // Add user to list await this.updateMembersList(state, local); return false; }, - async (connecting) => { + getLocalUserCanSend: async (connecting) => { if (connecting) return true; // If user has eligible roles, allow the update to be sent try { @@ -188,8 +224,8 @@ export class LivePresence< return false; } }, - true // We want to update the timestamp periodically so that we know if a user is active - ); + shouldUpdateTimestampPeriodically: true, // We want to update the timestamp periodically so that we know if a user is active + }); } catch (error: unknown) { // Update initialize state as fatal error this.initializeState = LiveDataObjectInitializeState.fatalError; @@ -203,7 +239,6 @@ export class LivePresence< // Throttled so that a developer can have multiple presence instances in their app in a performant manner. await this.updateInternal( this._currentPresence!.data.data, - this._currentPresence!.data.state, true, true ).catch(() => {}); @@ -217,35 +252,81 @@ export class LivePresence< if (this._synchronizer) { this._synchronizer.dispose(); } + this.disposeAudienceMemberChanges(); } /** * Returns a snapshot of the current list of presence objects being tracked. * See {@link LivePresenceUser} - * @param filter Optional. Presence state to filter enumeration to. + * @param filter Optional. Presence status to filter enumeration to. * @returns Array of presence objects. + * + * @example + ```ts + import { LiveShareClient, LivePresence, PresenceStatus } from "@microsoft/live-share"; + import { LiveShareHost } from "@microsoft/teams-js"; + + // Join the Fluid container and create the LivePresence instance + const host = LiveShareHost.create(); + const client = new LiveShareClient(host); + await client.join(); + const presence = await client.getDDS("unique-id", LivePresence); + // Initialize LivePresence + await presence.initialize(null); + + // Get online users + const onlineUsers = presence.getUsers(PresenceStatus.online); + + // Get all users + const allUsers = presence.getUsers(); + ``` */ - public getUsers(filter?: PresenceState): LivePresenceUser[] { + public getUsers(filter?: PresenceStatus): LivePresenceUser[] { if (!filter) return this._users; - return this._users.filter((user) => user.state == filter); + return this._users.filter((user) => user.status == filter); } /** - * Updates the local user's presence shared data object and/or state. + * Updates the local user's presence shared data object. * * @remarks * This will trigger the immediate broadcast of the users presence to all other clients. * - * @param data Optional. Data object to change. A deep copy of the data object is saved to avoid any future changes. - * @param state Optional. Presence state to change. + * @param data Data object to change. A deep copy of the data object is saved to avoid any future changes. * * @returns a void promise that resolves once the update event has been sent to the server. * * @throws error if initialization has not yet succeeded. * @throws error if the local user does not have the required roles defined through the `allowedRoles` prop in `.initialize()`. + * + * @example + ```ts + import { LiveShareClient, LivePresence, LivePresenceUser } from "@microsoft/live-share"; + import { LiveShareHost } from "@microsoft/teams-js"; + + // Delcare interface for custom presence data + interface IPresenceData { + favoriteColor: string; + } + + // Join the Fluid container and create the LivePresence instance + const host = LiveShareHost.create(); + const client = new LiveShareClient(host); + await client.join(); + const presence = await client.getDDS("unique-id", LivePresence); + + // Listen for changes to presence prior to calling initialize + presence.on("presenceChanged", async (user: LivePresenceUser, local: boolean) => { + console.log(user); + }); + // Initialize LivePresence with initial presence data for local user + await presence.initialize({ favoriteColor: "red" }); + // Update presence after calling initialize + await presence.update({ favoriteColor: "blue" }); + ``` */ - public async update(data?: TData, state?: PresenceState): Promise { - return await this.updateInternal(data, state); + public async update(data: TData): Promise { + return await this.updateInternal(data); } /** @@ -253,6 +334,31 @@ export class LivePresence< * See {@link LivePresenceUser} * @param clientId The ID of the client to retrieve. * @returns The current presence information for the client if they've connected to the space. + * + * @example + * Using this function, `LivePresence` can easily integrate with other Live Share features. + ```ts + import { LiveShareClient, LiveState, LivePresence } from "@microsoft/live-share"; + import { LiveShareHost } from "@microsoft/teams-js"; + + // Join the Fluid container and create the DDS instances + const host = LiveShareHost.create(); + const client = new LiveShareClient(host); + await client.join(); + const presence = await client.getDDS("unique-id-1", LivePresence); + const counter = await client.getDDS("unique-id-2", LiveState); + + // Initialize LivePresence + await presence.initialize(null); + + // Listen for changes to LiveState and get presence object for user that made change + counter.on("stateChanged", (count: number, local: boolean, clientId: string) => { + const user = presence.getUserForClient(clientId); + console.log("user", user, "changed the count to", count); + }); + // Initialize counter LiveState instance + await counter.initialize(0); + ``` */ public getUserForClient( clientId: string @@ -265,6 +371,22 @@ export class LivePresence< * See {@link LivePresenceUser} * @param userId The ID of the user to retrieve. * @returns The current presence information for the user if they've connected to the space. + * @example + * Using this function, `LivePresence` can easily integrate with other Teams features, such as Microsoft Graph. + ```ts + import { LiveShareClient, LiveState, LivePresence } from "@microsoft/live-share"; + import { LiveShareHost } from "@microsoft/teams-js"; + + // Join the Fluid container, create LivePresence, and initialize it + const host = LiveShareHost.create(); + const client = new LiveShareClient(host); + await client.join(); + const presence = await client.getDDS("unique-id", LivePresence); + await presence.initialize(null); + + // Get the user by user id + const user = presence.getUser("some-teams-user-id"); + ``` */ public getUser(userId: string): LivePresenceUser | undefined { return this._users.find((user) => user.userId == userId); @@ -274,8 +396,7 @@ export class LivePresence< * Internal method to send an update, with optional ability to throttle. */ private async updateInternal( - data?: TData, - state?: PresenceState, + data: TData | undefined, throttle: boolean = false, background: boolean = false ): Promise { @@ -297,7 +418,8 @@ export class LivePresence< // Broadcast state change const evtToSend = { - state: state ?? this._currentPresence.data.state, + // replace user status with online, update indicates active user. + status: PresenceStatus.online, data: cloneValue(data) ?? this._currentPresence.data.data, }; @@ -317,9 +439,9 @@ export class LivePresence< */ const localOnlyEvent = { data: evtToSend, - name: "", + name: "UpdatePresence", clientId: await this.waitUntilConnected(), - timestamp: 1, + timestamp: this.liveRuntime.getTimestamp(), }; await this.updateMembersList(localOnlyEvent, true); } @@ -348,14 +470,6 @@ export class LivePresence< // So if undefined if (!info) return false; - if (this.useTransientParticipantWorkaround(info)) { - return this.transientParticipantWorkaround( - evt, - localEvent, - info - ); - } - // normal flow return this.updateMembersListWithInfo(evt, localEvent, info); } catch (err) { this._logger?.sendErrorEvent( @@ -366,54 +480,13 @@ export class LivePresence< return false; } - /** - * For some reason, for non local users, tmp roster transiently doesn't contain a meeting participant. - * When the particpant is missing the `info` matches `defaultUserInfo`. - * @returns true if the info matches the default user info - */ - private useTransientParticipantWorkaround(info: IClientInfo): boolean { - const defaultUserInfo: IClientInfo = { - userId: info.userId, - roles: [UserMeetingRole.guest], - displayName: undefined, - }; - return JSON.stringify(info) === JSON.stringify(defaultUserInfo); - } - - /** - * Uses `updateMembersListWithInfo` with the latest value rather than using the incorrect default client info response. - * @returns true if user presence record was updated - */ - private transientParticipantWorkaround( - evt: LivePresenceReceivedEventData, - localEvent: boolean, - info: IClientInfo - ): boolean { - // when participant is missing, use existing information instead. - const user = this._users.find((user) => user.userId === info.userId); - if (user) { - const existingInfo: IClientInfo = { - userId: user.userId, - roles: user.roles, - displayName: user.displayName, - }; - return this.updateMembersListWithInfo( - evt, - localEvent, - existingInfo - ); - } - // This user has not yet been inserted, so we attempt to insert it with defaultUserInfo - return this.updateMembersListWithInfo(evt, localEvent, info); - } - private updateMembersListWithInfo( evt: LivePresenceReceivedEventData, localEvent: boolean, info: IClientInfo ): boolean { const emitEvent = (user: LivePresenceUser) => { - this._lastEmitPresenceStateMap.set(user.userId, user.state); + this._lastEmitPresenceStateMap.set(user.userId, user.status); this.emit( LivePresenceEvents.presenceChanged, user, @@ -448,7 +521,7 @@ export class LivePresence< isNewUser = false; } else if ( this._lastEmitPresenceStateMap.get(checkUser.userId) !== - checkUser.state + checkUser.status ) { // The user's PresenceState has changed emitEvent(checkUser); @@ -469,9 +542,89 @@ export class LivePresence< emitEvent(newUser); return true; } + + private audienceCallbacks = { + memberAdded: async (clientId: string, member: AzureMember) => { + this.audienceMemberChanged(clientId, PresenceStatus.online); + }, + memberRemoved: async (clientId: string, member: AzureMember) => { + this.audienceMemberChanged(clientId, PresenceStatus.offline); + }, + }; + + private listenForAudienceMemberChanges() { + this.liveRuntime.audience?.on( + "memberAdded", + this.audienceCallbacks.memberAdded + ); + + this.liveRuntime.audience?.on( + "memberRemoved", + this.audienceCallbacks.memberRemoved + ); + } + + private disposeAudienceMemberChanges() { + this.liveRuntime.audience?.off( + "memberAdded", + this.audienceCallbacks.memberAdded + ); + + this.liveRuntime.audience?.off( + "memberRemoved", + this.audienceCallbacks.memberRemoved + ); + } + + /** + * Will not create new Presence Users but will update to online if they leave and come back, and offline when they leave. + */ + private async audienceMemberChanged( + clientId: string, + status: PresenceStatus + ) { + const user = this.getUserForClient(clientId); + if (!user) { + return; + } + const connection = user?.getConnection(clientId); + if (!connection) return; + + const evtToSend = { + status, + data: connection.data, + }; + /** + * Create an event that is not sent to other clients, since all clients should create this event at the same time. + */ + const localOnlyEvent = { + data: evtToSend, + name: "UpdatePresence", + clientId: clientId, + timestamp: this.liveRuntime.getTimestamp(), + }; + await this.updateMembersList(localOnlyEvent, true); + } + + /** + * initializingFirstTime is run only once by the first client to create the DataObject. Here we use it to + * initialize the state of the DataObject. + */ + protected async initializingFirstTime() { + this.debugInfo = `LivePresence-${this.id}`; + } } +export type LivePresence = + LivePresenceClass; + +// eslint-disable-next-line no-redeclare +export const LivePresence = (() => { + const kind = LivePresenceClass; + return kind as typeof kind & SharedObjectKind>; +})(); + /** - * Register `LivePresence` as an available `LoadableObjectClass` for use in packages that support dynamic object loading, such as `@microsoft/live-share-turbo`. + * Register `LivePresence` as an available `SharedObjectKind` for use in dynamic object loading. */ DynamicObjectRegistry.registerObjectClass(LivePresence, LivePresence.TypeName); diff --git a/packages/live-share/src/LivePresenceConnection.ts b/packages/live-share/src/LivePresenceConnection.ts index e31351985..625a38c18 100644 --- a/packages/live-share/src/LivePresenceConnection.ts +++ b/packages/live-share/src/LivePresenceConnection.ts @@ -1,11 +1,11 @@ -import { cloneValue } from "./internals"; -import { LiveEvent } from "./LiveEvent"; import { LivePresenceReceivedEventData, - PresenceState, -} from "./LivePresenceUser"; -import { LiveShareRuntime } from "./LiveShareRuntime"; -import { TimeInterval } from "./TimeInterval"; + PresenceStatus, +} from "./LivePresenceUser.js"; +import { LiveShareRuntime } from "./internals/LiveShareRuntime.js"; +import { TimeInterval } from "./TimeInterval.js"; +import { cloneValue, isNewerEvent } from "./internals/utils.js"; +import { LivePresenceData } from "./LivePresence.js"; /** * A connection that presence is being tracked for. @@ -13,7 +13,7 @@ import { TimeInterval } from "./TimeInterval"; * A user can join from multiple devices. If they do, they will have multiple connections and a distinct clientId on each device. * If the client is disconnected for any reason, and they have to reconnect, they will get a new clientId and thus a new connection. */ -export class LivePresenceConnection { +export class LivePresenceConnection { /** * @hidden */ @@ -39,20 +39,35 @@ export class LivePresenceConnection { } /** - * Connections current state. + * Connections current status. * * @remarks - * This is automatically set to `PresenceState.offline` if the users client hasn't sent updates + * This is automatically set to `PresenceStatus.offline` if the users client hasn't sent updates * for a period of time. */ - public get state(): PresenceState { - return this.hasExpired() ? PresenceState.offline : this._evt.data.state; + public get status(): PresenceStatus { + if (this._evt.data.status !== PresenceStatus.online) { + return this._evt.data.status; + } else if (this.hasExpired()) { + return PresenceStatus.away; + } + + return this._evt.data.status; + } + + /** + * @deprecated + * Please use {@link LivePresenceConnection.status} instead. + * This will be removed in a future release. + */ + public get state(): PresenceStatus { + return this.status; } /** * Optional data shared by the user. */ - public get data(): TData | undefined { + public get data(): TData { return cloneValue(this._evt.data.data); } @@ -65,7 +80,7 @@ export class LivePresenceConnection { `LivePresenceConnection.updateConnection called with event with different clientId` ); } - if (!LiveEvent.isNewer(this._evt, evt)) return; + if (!isNewerEvent(this._evt, evt)) return; this._evt = evt; } diff --git a/packages/live-share/src/LivePresenceUser.ts b/packages/live-share/src/LivePresenceUser.ts index 1f973805d..fb9d4a190 100644 --- a/packages/live-share/src/LivePresenceUser.ts +++ b/packages/live-share/src/LivePresenceUser.ts @@ -3,53 +3,59 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { LiveEvent } from "./LiveEvent"; -import { IClientInfo, ILiveEvent, UserMeetingRole } from "./interfaces"; -import { TimeInterval } from "./TimeInterval"; -import { cloneValue } from "./internals"; -import { LiveShareRuntime } from "./LiveShareRuntime"; -import { LivePresenceConnection } from "./LivePresenceConnection"; +import { IClientInfo, ILiveEvent, UserMeetingRole } from "./interfaces.js"; +import { TimeInterval } from "./TimeInterval.js"; +import { LiveShareRuntime } from "./internals/LiveShareRuntime.js"; +import { LivePresenceConnection } from "./LivePresenceConnection.js"; +import { cloneValue, isNewerEvent } from "./internals/utils.js"; +import { LivePresenceData } from "./LivePresence.js"; /** - * List of possible presence states. + * List of possible presence status states. */ -export enum PresenceState { +export enum PresenceStatus { /** * The user is online. Default state while user has at least one client connected. */ online = "online", /** - * The user is away. Applications can set this state based on the users activity. + * The user is away. Automatically set for users after their client has stopped sending + * updates for a period of time. @see LivePresence.expirationPeriod. */ away = "away", /** - * The user is offline. Automatically set for users after their client has stopped sending - * updates for a period of time. + * The user is offline. */ offline = "offline", } +/** + * @deprecated + * Use {@link PresenceStatus} instead. + */ +export const PresenceState = PresenceStatus; + /** * @hidden */ -export interface ILivePresenceEvent { - state: PresenceState; - data?: TData; +export interface ILivePresenceEvent { + status: PresenceStatus; + data: TData; } /** * @hidden */ -export type LivePresenceReceivedEventData = ILiveEvent< - ILivePresenceEvent ->; +export type LivePresenceReceivedEventData< + TData extends LivePresenceData = any, +> = ILiveEvent>; /** * A user that presence is being tracked for. */ -export class LivePresenceUser { +export class LivePresenceUser { private _lastUpdateTime: number; private _connections: Map> = new Map(); @@ -91,18 +97,33 @@ export class LivePresenceUser { * Users current state. * * @remarks - * This is automatically set to `PresenceState.offline` if the users client hasn't sent updates + * This is automatically set to `PresenceStatus.offline` if the users client hasn't sent updates * for a period of time. */ - public get state(): PresenceState { - return this.hasExpired() ? PresenceState.offline : this._evt.data.state; + public get status(): PresenceStatus { + if (this._evt.data.status !== PresenceStatus.online) { + return this._evt.data.status; + } else if (this.hasExpired()) { + return PresenceStatus.away; + } + + return this._evt.data.status; + } + + /** + * @deprecated + * Please use {@link LivePresenceConnection.status} instead. + * This will be removed in a future release. + */ + public get state(): PresenceStatus { + return this.status; } /** * Optional data shared by the user. Returns data from connection with most recent event. * Client connection specific data is available from each connection. */ - public get data(): TData | undefined { + public get data(): TData { return cloneValue(this._evt.data.data); } @@ -118,12 +139,12 @@ export class LivePresenceUser { * See {@link LivePresenceConnection} */ public getConnections( - filter?: PresenceState + filter?: PresenceStatus ): LivePresenceConnection[] { const list: LivePresenceConnection[] = []; this._connections.forEach((connection) => { // Ensure connection matches filter - if (filter == undefined || connection.state == filter) { + if (filter == undefined || connection.status == filter) { list.push(connection); } }); @@ -160,16 +181,20 @@ export class LivePresenceUser { const remoteUserConvertedToLocal = this.updateClients(evt, localEvent); const currentEvent = this._evt; const currentClientInfo = this._clientInfo; - if (LiveEvent.isNewer(currentEvent, evt)) { - // Save updated event - this._evt = evt; + if (isNewerEvent(currentEvent, evt)) { + // Save updated event, but change state of LivePresenceUser to reflect aggregate of connection states. + const aggregateState = this.aggregateConnectionState(); + const aggregateStateEvent = cloneValue(evt); + aggregateStateEvent.data.status = aggregateState; + + this._evt = aggregateStateEvent; this._clientInfo = info; this._lastUpdateTime = this._liveRuntime.getTimestamp(); // Has anything changed? return ( remoteUserConvertedToLocal || - evt.data.state != currentEvent.data.state || + aggregateStateEvent.data.status != currentEvent.data.status || JSON.stringify(info) != JSON.stringify(currentClientInfo) || JSON.stringify(evt.data.data) != JSON.stringify(currentEvent.data.data) @@ -179,6 +204,25 @@ export class LivePresenceUser { return remoteUserConvertedToLocal; } + private aggregateConnectionState(): PresenceStatus { + return Array.from(this._connections.values()) + .map((c) => c.status) + .reduce((previous, current) => { + if ( + previous === PresenceStatus.online || + current === PresenceStatus.online + ) { + return PresenceStatus.online; + } else if ( + previous === PresenceStatus.away || + current === PresenceStatus.away + ) { + return PresenceStatus.away; + } + return PresenceStatus.offline; + }, PresenceStatus.offline); + } + /** * @hidden */ diff --git a/packages/live-share/src/LiveShareClient.ts b/packages/live-share/src/LiveShareClient.ts index 6340f98f6..16eb42ecc 100644 --- a/packages/live-share/src/LiveShareClient.ts +++ b/packages/live-share/src/LiveShareClient.ts @@ -3,7 +3,8 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { LiveShareTokenProvider, getInsecureTokenProvider } from "./internals"; +import { waitForDelay } from "./internals/utils.js"; +import { LiveShareTokenProvider } from "./internals/LiveShareTokenProvider.js"; import { AzureClient, AzureContainerServices, @@ -18,11 +19,15 @@ import { ITimestampProvider, IRoleVerifier, ILiveShareJoinResults, -} from "./interfaces"; -import { LocalTimestampProvider } from "./LocalTimestampProvider"; -import { TestLiveShareHost } from "./TestLiveShareHost"; -import { LiveShareRuntime } from "./LiveShareRuntime"; -import { getLiveContainerSchema } from "./schema-injection-utils"; +} from "./interfaces.js"; +import { BaseLiveShareClient } from "./internals/BaseLiveShareClient.js"; +import { LocalTimestampProvider } from "./LocalTimestampProvider.js"; +import { TestLiveShareHost } from "./TestLiveShareHost.js"; +import { LiveShareRuntime } from "./internals/LiveShareRuntime.js"; +import { getLiveContainerSchema } from "./internals/schema-injection-utils.js"; +import { ExpectedError, UnexpectedError } from "./errors.js"; +import { FluidCompatibilityMode } from "./internals/consts.js"; +import { isTestHostWithInsecureTokenProvider } from "./internals/type-guards.js"; /** * @hidden @@ -86,32 +91,50 @@ export interface ILiveShareClientOptions { /** * Client used to connect to fluid containers within a Microsoft Teams context. */ -export class LiveShareClient { - private _host: ILiveShareHost = TestLiveShareHost.create( - undefined, - undefined - ); +export class LiveShareClient extends BaseLiveShareClient { + private _host: ILiveShareHost; private readonly _options: ILiveShareClientOptions; - private readonly _runtime: LiveShareRuntime; private _results: ILiveShareJoinResults | undefined; + /** + * @hidden + */ + protected getDDSErrorJoinFunctionText: string = "join"; + /** * Creates a new `LiveShareClient` instance. * @param host Host for the current Live Share session. * @param options Optional. Configuration options for the client. + * + * @example + ```ts + import { LiveShareClient, LivePresence } from "@microsoft/live-share"; + // Import ILiveShareHost instance. Most common option is using the teams-js SDK + import { LiveShareHost } from "@microsoft/teams-js"; + + // Join the Fluid container + const host = LiveShareHost.create(); + const client = new LiveShareClient(host); + await client.join(); + + // TODO: start collab logic + ``` */ constructor(host: ILiveShareHost, options?: ILiveShareClientOptions) { // Validate host passed in - if (!host) { - throw new Error( - `LiveShareClient: prop \`host\` is \`${host}\` when it is expected to be a non-optional value of type \`ILiveShareHost\`. Please ensure \`host\` is defined before initializing \`LiveShareClient\`.` - ); - } - if (typeof host.getFluidTenantInfo != "function") { - throw new Error( - `LiveShareClient: \`host.getFluidTenantInfo\` is of type \`${typeof host.getFluidTenantInfo}\` when it is expected to be a type of \`function\`. For more information, review the \`ILiveShareHost\` interface.` - ); - } + ExpectedError.assert( + !!host, + "LiveShareClient:constructor", + `prop \`host\` is \`${host}\` when it is expected to be a non-optional value of type \`ILiveShareHost\`.`, + "Please ensure `host` is defined before initializing `LiveShareClient`." + ); + ExpectedError.assert( + typeof host.getFluidTenantInfo === "function", + "LiveShareClient:constructor", + `\`host.getFluidTenantInfo\` is of type \`${typeof host.getFluidTenantInfo}\` when it is expected to be a type of \`function\`.`, + "For more information, review the `ILiveShareHost` interface." + ); + super(new LiveShareRuntime(host, options, true)); this._host = host; // Save options this._options = { @@ -123,6 +146,15 @@ export class LiveShareClient { this._runtime = new LiveShareRuntime(this._host, this._options, true); } + /** + * @remarks + * Includes additional information, such as whether the local user created the container. + * See {@link BaseLiveShareClient.results} for more information. + */ + public get results(): ILiveShareJoinResults | undefined { + return this._results; + } + /** * If true the client is configured to use a local test server. */ @@ -137,27 +169,18 @@ export class LiveShareClient { public maxContainerLookupTries = 3; /** - * Setting for whether `LiveDataObject` instances using `LiveObjectSynchronizer` can send background updates. - * Default value is `true`. - * - * @remarks - * This is useful for scenarios where there are a large number of participants in a session, since service performance degrades as more socket connections are opened. - * Intended for use when a small number of users are intended to be "in control", such as the `LiveFollowMode` class's `startPresenting()` feature. - * There should always be at least one user in the session that has `canSendBackgroundUpdates` set to true. - * Set to true when the user is eligible to send background updates (e.g., "in control"), or false when that user is not in control. - * This setting will not prevent the local user from explicitly changing the state of objects using `LiveObjectSynchronizer`, such as `.set()` in `LiveState`. - * Impacts background updates of `LiveState`, `LivePresence`, `LiveTimer`, and `LiveFollowMode`. + * @deprecated + * Use {@link LiveShareClient.join} instead. */ - public get canSendBackgroundUpdates(): boolean { - return this._runtime.canSendBackgroundUpdates; - } - - public set canSendBackgroundUpdates(value: boolean) { - this._runtime.canSendBackgroundUpdates = value; + public async joinContainer( + fluidContainerSchema?: ContainerSchema, + onContainerFirstCreated?: (container: IFluidContainer) => void + ): Promise { + return this.join(fluidContainerSchema, onContainerFirstCreated); } /** - * Connects to the fluid container for the current teams context. + * Connects to the Fluid container for the relevant context (e.g., a Teams meeting). * * @remarks * The first client joining the container will create the container resulting in the @@ -166,11 +189,53 @@ export class LiveShareClient { * @param fluidContainerSchema Fluid objects to create. * @param onContainerFirstCreated Optional. Callback that's called when the container is first created. * @returns the results of join container. + * + * @example + * The following is an example using no optional props: + ```ts + import { LiveShareClient, LivePresence } from "@microsoft/live-share"; + import { LiveShareHost } from "@microsoft/teams-js"; + + // Join the Fluid container + const host = LiveShareHost.create(); + const client = new LiveShareClient(host); + await client.join(); + + // Create a DDS + const presence = await client.getDDS("unique-id", LivePresence, (dds) => { + console.log("first created dds", dds); + }); + ``` + * @example + * The following is an example using the optional props: + ```ts + import { LiveShareClient, LivePresence, LiveState } from "@microsoft/live-share"; + import { LiveShareHost } from "@microsoft/teams-js"; + import { ContainerSchema } from "fluid-framework"; + + // Join the Fluid container + const host = LiveShareHost.create(); + const client = new LiveShareClient(host); + const schema = { + initialObjects: { + presence: LivePresence + } + } as const satisfies ContainerSchema; + const { container } = await client.join(schema, (container) => { + console.log("First created container", container); + }); + const presence = container.initialObjects.presence; + + // Can still dynamically get DDS's that were not in schema + const counter = await client.getDDS("unique-id", LiveState); + ``` */ - public async joinContainer( - fluidContainerSchema: ContainerSchema, - onContainerFirstCreated?: (container: IFluidContainer) => void - ): Promise { + public async join( + fluidContainerSchema?: TContainerSchema, + onContainerFirstCreated?: ( + container: IFluidContainer + ) => void + ): Promise> { performance.mark(`TeamsSync: join container`); try { // Start runtime if needed @@ -178,7 +243,7 @@ export class LiveShareClient { // Apply runtime to ContainerSchema const schema = getLiveContainerSchema( - fluidContainerSchema, + this.getContainerSchema(fluidContainerSchema), this._runtime ); @@ -194,24 +259,29 @@ export class LiveShareClient { let endpoint: string | undefined = frsTenantInfo.serviceEndpoint; if (!endpoint) { - if (serviceEndpointMap.has(frsTenantInfo.serviceEndpoint)) { - endpoint = serviceEndpointMap.get( - frsTenantInfo.serviceEndpoint - ); - } else { - throw new Error( - `LiveShareClient:joinContainer - unable to find fluid endpoint for: ${frsTenantInfo.serviceEndpoint}` - ); - } + UnexpectedError.assert( + serviceEndpointMap.has(frsTenantInfo.serviceEndpoint), + "LiveShareClient:join", + `unable to find fluid endpoint for: ${frsTenantInfo.serviceEndpoint}` + ); + endpoint = serviceEndpointMap.get( + frsTenantInfo.serviceEndpoint + ); } // Is this a local config? if (frsTenantInfo.tenantId == "local") { - config = { - type: "local", - endpoint: endpoint!, - tokenProvider: await getInsecureTokenProvider(), - }; + if (isTestHostWithInsecureTokenProvider(this._host)) { + config = { + type: "local", + endpoint: endpoint!, + tokenProvider: this._host.insecureTokenProvider, + }; + } else { + throw new Error( + `LiveShareClient:join: unable to use local connection type with test host that that does not include an insecure token provider, please configure an insecure token provider.` + ); + } } else { config = { type: "remote", @@ -242,11 +312,12 @@ export class LiveShareClient { performance.mark(`TeamsSync: container connecting`); - this._results = { + const results = { ...result[0], timestampProvider: this._runtime.timestampProvider, }; - return this._results; + this._results = results; + return results; } finally { performance.measure( `TeamsSync: container joined`, @@ -255,13 +326,17 @@ export class LiveShareClient { } } - private async getOrCreateContainer( + private async getOrCreateContainer< + const TContainerSchema extends ContainerSchema, + >( client: AzureClient, - fluidContainerSchema: ContainerSchema, + fluidContainerSchema: TContainerSchema, tries: number, - onInitializeContainer?: (container: IFluidContainer) => void + onInitializeContainer?: ( + container: IFluidContainer + ) => void ): Promise<{ - container: IFluidContainer; + container: IFluidContainer; services: AzureContainerServices; created: boolean; }> { @@ -281,14 +356,15 @@ export class LiveShareClient { created: false, ...(await client.getContainer( containerInfo.containerId, - fluidContainerSchema + fluidContainerSchema, + FluidCompatibilityMode )), }; } else if ( tries < this.maxContainerLookupTries && containerInfo.retryAfter > 0 ) { - await this.wait(containerInfo.retryAfter); + await waitForDelay(containerInfo.retryAfter); return await this.getOrCreateContainer( client, fluidContainerSchema, @@ -302,20 +378,28 @@ export class LiveShareClient { } } - private async createNewContainer( + private async createNewContainer< + const TContainerSchema extends ContainerSchema, + >( client: AzureClient, - fluidContainerSchema: ContainerSchema, + fluidContainerSchema: TContainerSchema, tries: number, - onInitializeContainer?: (container: IFluidContainer) => void + onInitializeContainer?: ( + container: IFluidContainer + ) => void ): Promise<{ - container: IFluidContainer; + container: IFluidContainer; services: AzureContainerServices; created: boolean; }> { // Create and initialize container const { container, services } = await client.createContainer( - fluidContainerSchema + fluidContainerSchema, + FluidCompatibilityMode ); + + await this.addTurboFolder(container); + if (onInitializeContainer) { onInitializeContainer(container); } @@ -324,9 +408,8 @@ export class LiveShareClient { const newContainerId = await container.attach(); // Attempt to save container ID mapping - const containerInfo = await this._host.setFluidContainerId( - newContainerId - ); + const containerInfo = + await this._host.setFluidContainerId(newContainerId); if (containerInfo.containerState != ContainerState.added) { // Delete created container container.dispose(); @@ -336,19 +419,14 @@ export class LiveShareClient { created: false, ...(await client.getContainer( containerInfo.containerId!, - fluidContainerSchema + fluidContainerSchema, + FluidCompatibilityMode )), }; } else { return { container, services, created: true }; } } - - private wait(delay: number): Promise { - return new Promise((resolve) => { - setTimeout(() => resolve(), delay); - }); - } } function getIsTestClient( diff --git a/packages/live-share/src/LiveState.ts b/packages/live-share/src/LiveState.ts index af38d76f2..5c99cf58e 100644 --- a/packages/live-share/src/LiveState.ts +++ b/packages/live-share/src/LiveState.ts @@ -3,28 +3,28 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { DataObjectFactory } from "@fluidframework/aqueduct"; -import { assert } from "@fluidframework/common-utils"; -import { IEvent } from "@fluidframework/common-definitions"; +import { DataObjectFactory } from "@fluidframework/aqueduct/legacy"; +import { IEvent } from "@fluidframework/core-interfaces"; import { ILiveEvent, LiveDataObjectInitializeState, UserMeetingRole, -} from "./interfaces"; -import { cloneValue, TelemetryEvents } from "./internals"; +} from "./interfaces.js"; import { LiveDataObjectInitializeNotNeededError, LiveDataObjectNotInitializedError, UnexpectedError, -} from "./errors"; -import { LiveTelemetryLogger } from "./LiveTelemetryLogger"; -import { LiveEvent } from "./LiveEvent"; -import { LiveObjectSynchronizer } from "./LiveObjectSynchronizer"; -import { DynamicObjectRegistry } from "./DynamicObjectRegistry"; -import { LiveDataObject } from "./LiveDataObject"; +} from "./errors.js"; +import { LiveTelemetryLogger } from "./LiveTelemetryLogger.js"; +import { LiveObjectSynchronizer } from "./internals/LiveObjectSynchronizer.js"; +import { DynamicObjectRegistry } from "./internals/DynamicObjectRegistry.js"; +import { LiveDataObject } from "./internals/LiveDataObject.js"; +import { SharedObjectKind } from "fluid-framework"; +import { TelemetryEvents } from "./internals/consts.js"; +import { cloneValue, isNewerEvent } from "./internals/utils.js"; /** - * Events supported by [LiveState` object. + * Events supported by {@link LiveState} object. */ export enum LiveStateEvents { /** @@ -34,12 +34,12 @@ export enum LiveStateEvents { } /** - * Event typings for `LiveState` class. + * Event typings for {@link LiveState} class. * @template TState State object that's synchronized with the state. */ export interface ILiveStateEvents extends IEvent { /** - * An `LiveState` objects state has changed. + * An {@link LiveState} objects state has changed. * @param event Name of event. * @param listener Function called when event is triggered. * @param listener.state The new state. Can be the same as the previous state. @@ -67,7 +67,7 @@ export interface ILiveStateEvents extends IEvent { * changes. * @template TState Optional data object that's synchronized with the state. */ -export class LiveState extends LiveDataObject<{ +export class LiveStateClass extends LiveDataObject<{ Events: ILiveStateEvents; }> { private _logger?: LiveTelemetryLogger; @@ -84,8 +84,8 @@ export class LiveState extends LiveDataObject<{ * The objects fluid type factory. */ public static readonly factory = new DataObjectFactory( - LiveState.TypeName, - LiveState, + LiveStateClass.TypeName, + LiveStateClass, [], {} ); @@ -108,6 +108,27 @@ export class LiveState extends LiveDataObject<{ * @throws error when `.initialize()` has already been called for this class instance. * @throws fatal error when `.initialize()` has already been called for an object of same id but with a different class instance. * This is most common when using dynamic objects through Fluid. + * + * @example + ```ts + import { LiveShareClient, LiveState } from "@microsoft/live-share"; + import { LiveShareHost } from "@microsoft/teams-js"; + + // Join the Fluid container and create the LiveState instance + const host = LiveShareHost.create(); + const client = new LiveShareClient(host); + await client.join(); + const counter = await client.getDDS("unique-id", LiveState); + + // Listen for changes to state prior to calling initialize + counter.on("stateChanged", async (count: number, local: boolean, clientId: string) => { + console.log(count); + }); + // Initialize LiveState with initial state + await counter.initialize(0); + // Set changes to state after calling initialize + await counter.set(counter.state + 1); + ``` */ public async initialize( initialState: TState, @@ -145,14 +166,14 @@ export class LiveState extends LiveDataObject<{ this.liveRuntime ); try { - await this._synchronizer.start( + await this._synchronizer.start({ initialState, - async (evt, sender, local) => { + updateState: async (evt, sender, local) => { // Check for state change. // If it was valid, this will override the local user's previous value. return await this.onReceivedStateEvent(evt, sender, local); }, - async (connecting) => { + getLocalUserCanSend: async (connecting) => { if (connecting) return true; // If user has eligible roles, allow the update to be sent try { @@ -160,8 +181,8 @@ export class LiveState extends LiveDataObject<{ } catch { return false; } - } - ); + }, + }); } catch (error: unknown) { // Update initialize state as fatal error this.initializeState = LiveDataObjectInitializeState.fatalError; @@ -191,6 +212,27 @@ export class LiveState extends LiveDataObject<{ * * @throws error if initialization has not yet succeeded. * @throws error if the local user does not have the required roles defined through the `allowedRoles` prop in `.initialize()`. + * + * @example + ```ts + import { LiveShareClient, LiveState } from "@microsoft/live-share"; + import { LiveShareHost } from "@microsoft/teams-js"; + + // Join the Fluid container and create the LiveState instance + const host = LiveShareHost.create(); + const client = new LiveShareClient(host); + await client.join(); + const counter = await client.getDDS("unique-id", LiveState); + + // Listen for changes to state prior to calling initialize + counter.on("stateChanged", async (count: number, local: boolean, clientId: string) => { + console.log(count); + }); + // Initialize LiveState with initial state + await counter.initialize(0); + // Set changes to state after calling initialize + await counter.set(counter.state + 1); + ``` */ public async set(state: TState): Promise { LiveDataObjectNotInitializedError.assert( @@ -213,7 +255,11 @@ export class LiveState extends LiveDataObject<{ * The current state. */ private get latestEvent(): ILiveEvent { - assert(this._latestEvent !== undefined, "LiveState is not initialized"); + UnexpectedError.assert( + this._latestEvent !== undefined, + "LiveState:latestEvent", + "LiveState is not initialized" + ); return this._latestEvent; } @@ -236,8 +282,7 @@ export class LiveState extends LiveDataObject<{ this._allowedRoles ); // Ensure that state is allowed, newer, and not the initial state. - if (!allowed || !LiveEvent.isNewer(this.latestEvent, evt)) - return false; + if (!allowed || !isNewerEvent(this.latestEvent, evt)) return false; if ( JSON.stringify(this.latestEvent.data) === JSON.stringify(evt.data) @@ -274,9 +319,25 @@ export class LiveState extends LiveDataObject<{ } ); } + + /** + * initializingFirstTime is run only once by the first client to create the DataObject. Here we use it to + * initialize the state of the DataObject. + */ + protected async initializingFirstTime() { + this.debugInfo = `LivePresence-${this.id}`; + } } +export type LiveState = LiveStateClass; + +// eslint-disable-next-line no-redeclare +export const LiveState = (() => { + const kind = LiveStateClass; + return kind as typeof kind & SharedObjectKind; +})(); + /** - * Register `LiveState` as an available `LoadableObjectClass` for use in packages that support dynamic object loading, such as `@microsoft/live-share-turbo`. + * Register `LiveState` as an available `SharedObjectKind` for use in dynamic object loading. */ DynamicObjectRegistry.registerObjectClass(LiveState, LiveState.TypeName); diff --git a/packages/live-share/src/LiveTelemetryLogger.ts b/packages/live-share/src/LiveTelemetryLogger.ts index 92335321d..9e5c59c8d 100644 --- a/packages/live-share/src/LiveTelemetryLogger.ts +++ b/packages/live-share/src/LiveTelemetryLogger.ts @@ -4,19 +4,17 @@ */ import { - ITelemetryErrorEvent, - ITelemetryGenericEvent, - ITelemetryPerformanceEvent, - ITelemetryProperties, -} from "@fluidframework/common-definitions"; -import { IRuntimeSignaler } from "./LiveEventScope"; -import { LiveShareClient } from "./LiveShareClient"; -import { LiveShareRuntime } from "./LiveShareRuntime"; + ITelemetryBaseEvent, + ITelemetryBaseProperties, + LogLevel, +} from "@fluidframework/core-interfaces"; +import { IRuntimeSignaler } from "./internals/LiveEventScope.js"; +import { LiveShareRuntime } from "./internals/LiveShareRuntime.js"; /** * Properties included on all events sent by `LiveTelemetryLogger`. */ -export interface ILiveTelemetryProperties extends ITelemetryProperties { +export interface ILiveTelemetryProperties extends ITelemetryBaseProperties { /** * Optional. ID of the client if it's been assigned by the runtime. */ @@ -38,6 +36,11 @@ export interface ILiveTelemetryProperties extends ITelemetryProperties { * Time that the event occurred. The timestamp is generated by `_liveRuntime.getTimestamp`. */ timestamp: string; + + /** + * category of the event, like "error", "performance", "generic", etc. + */ + category: string; } /** @@ -70,11 +73,15 @@ export class LiveTelemetryLogger { additionalProperties?: Partial ): void { if (this._runtime.logger) { - const evt: ITelemetryGenericEvent = this.createTelemetryEvent( - eventName, - additionalProperties - ); - this._runtime.logger.sendTelemetryEvent(evt, error); + const evt: ITelemetryBaseEvent = { + ...this.createTelemetryEvent( + eventName, + "default", + additionalProperties + ), + error: this.parseErrorMessage(error), + }; + this._runtime.logger.send(evt, LogLevel.default); } } @@ -90,11 +97,15 @@ export class LiveTelemetryLogger { additionalProperties?: Partial ): void { if (this._runtime.logger) { - const evt: ITelemetryErrorEvent = this.createTelemetryEvent( - eventName, - additionalProperties - ); - this._runtime.logger.sendErrorEvent(evt, error); + const evt: ITelemetryBaseEvent = { + ...this.createTelemetryEvent( + eventName, + "error", + additionalProperties + ), + error: this.parseErrorMessage(error), + }; + this._runtime.logger.send(evt, LogLevel.error); } } @@ -112,16 +123,22 @@ export class LiveTelemetryLogger { additionalProperties?: Partial ): void { if (this._runtime.logger) { - const evt: ITelemetryPerformanceEvent = { + const evt: ITelemetryBaseEvent = { duration: duration, - ...this.createTelemetryEvent(eventName, additionalProperties), + ...this.createTelemetryEvent( + eventName, + "performance", + additionalProperties + ), + error: this.parseErrorMessage(error), }; - this._runtime.logger.sendPerformanceEvent(evt, error); + this._runtime.logger.send(evt, LogLevel.error); } } private createTelemetryEvent( eventName: string, + category: string, additionalProperties?: Partial ): T { const now = this._liveRuntime.getTimestamp(); @@ -133,6 +150,7 @@ export class LiveTelemetryLogger { now ), timestamp: now, + category, ...additionalProperties, } as ILiveTelemetryProperties as T; } @@ -143,4 +161,17 @@ export class LiveTelemetryLogger { ): string { return `${clientId}:${timestamp}`; } + + private parseErrorMessage(error?: any): string { + if (!error) { + return `${error}`; + } + if (typeof error === "string") { + return error; + } + if (typeof error.message === "string") { + return error.message; + } + return `${JSON.stringify(error)}`; + } } diff --git a/packages/live-share/src/LiveTimer.ts b/packages/live-share/src/LiveTimer.ts index bfef199cd..ff82f0d24 100644 --- a/packages/live-share/src/LiveTimer.ts +++ b/packages/live-share/src/LiveTimer.ts @@ -3,23 +3,24 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { DataObjectFactory } from "@fluidframework/aqueduct"; -import { LiveObjectSynchronizer } from "./LiveObjectSynchronizer"; +import { DataObjectFactory } from "@fluidframework/aqueduct/legacy"; +import { LiveObjectSynchronizer } from "./internals/LiveObjectSynchronizer.js"; import { IClientTimestamp, ILiveEvent, LiveDataObjectInitializeState, UserMeetingRole, -} from "./interfaces"; -import { IEvent } from "@fluidframework/common-definitions"; -import { LiveEvent } from "./LiveEvent"; -import { DynamicObjectRegistry } from "./DynamicObjectRegistry"; -import { LiveDataObject } from "./LiveDataObject"; +} from "./interfaces.js"; +import { IEvent } from "@fluidframework/core-interfaces"; +import { DynamicObjectRegistry } from "./internals/DynamicObjectRegistry.js"; +import { LiveDataObject } from "./internals/LiveDataObject.js"; import { LiveDataObjectInitializeNotNeededError, LiveDataObjectNotInitializedError, UnexpectedError, -} from "./errors"; +} from "./errors.js"; +import { SharedObjectKind } from "fluid-framework"; +import { isEventNewer } from "./index.internal.js"; export interface ITimerConfigData { /** @@ -100,7 +101,7 @@ export interface ILiveTimerEvents extends IEvent { (event: "onTick", listener: (milliRemaining: number) => void): any; } -export class LiveTimer extends LiveDataObject<{ +export class LiveTimerClass extends LiveDataObject<{ Events: ILiveTimerEvents; }> { private _currentConfig: ITimerConfigEvent = { @@ -125,8 +126,8 @@ export class LiveTimer extends LiveDataObject<{ * The objects fluid type factory. */ public static readonly factory = new DataObjectFactory( - LiveTimer.TypeName, - LiveTimer, + LiveTimerClass.TypeName, + LiveTimerClass, [], {} ); @@ -160,6 +161,62 @@ export class LiveTimer extends LiveDataObject<{ * @throws error when `.initialize()` has already been called for this class instance. * @throws fatal error when `.initialize()` has already been called for an object of same id but with a different class instance. * This is most common when using dynamic objects through Fluid. + * + * @example + ```ts + import { + LiveShareClient, + LiveTimer, + LiveTimerEvents, + ITimerConfig, + } from "@microsoft/live-share"; + import { LiveShareHost } from "@microsoft/teams-js"; + + // Join the Fluid container and create LiveTimer instance + const host = LiveShareHost.create(); + const client = new LiveShareClient(host); + await client.join(); + const timer = await client.getDDS("unique-id", LiveTimer); + + // Register listeners for timer changes before initializing + + // Register listener for when the timer starts its countdown + timer.on(LiveTimerEvents.started, (config: ITimerConfig, local: boolean) => { + // Update UI to show timer has started + }); + + // Register listener for when a paused timer has resumed + timer.on(LiveTimerEvents.played, (config: ITimerConfig, local: boolean) => { + // Update UI to show timer has resumed + }); + + // Register listener for when a playing timer has paused + timer.on(LiveTimerEvents.paused, (config: ITimerConfig, local: boolean) => { + // Update UI to show timer has paused + }); + + // Register listener for when a playing timer has finished + timer.on(LiveTimerEvents.finished, (config: ITimerConfig) => { + // Update UI to show timer is finished + }); + + // Register listener for the timer progressed by 20 milliseconds + timer.on(LiveTimerEvents.onTick, (milliRemaining: number) => { + // Update UI to show remaining time + }); + + // Initialize to begin synchronizing timer events + await timer.initialize(); + + // Start a 60 second timer for users in session + await timer.start(1000 * 60); + + // Pause the timer for users in session + await timer.pause(); + + // Resume the timer for users in session + await timer.play(); + ``` */ public async initialize(allowedRoles?: UserMeetingRole[]): Promise { LiveDataObjectInitializeNotNeededError.assert( @@ -185,14 +242,14 @@ export class LiveTimer extends LiveDataObject<{ this.liveRuntime ); try { - await this._synchronizer.start( - this._currentConfig.data, - async (state, sender) => { + await this._synchronizer.start({ + initialState: this._currentConfig.data, + updateState: async (state, sender) => { // Check for state change. // If it was valid, this will override the local user's previous value. return await this.remoteConfigReceived(state, sender); }, - async (connecting) => { + getLocalUserCanSend: async (connecting) => { if (connecting) return true; // If user has eligible roles, allow the update to be sent try { @@ -200,8 +257,8 @@ export class LiveTimer extends LiveDataObject<{ } catch { return false; } - } - ); + }, + }); } catch (error: unknown) { // Update initialize state as fatal error this.initializeState = LiveDataObjectInitializeState.fatalError; @@ -234,6 +291,34 @@ export class LiveTimer extends LiveDataObject<{ * * @throws error if initialization has not yet succeeded. * @throws error if the local user does not have the required roles defined through the `allowedRoles` prop in `.initialize()`. + * + * @example + ```ts + import { + LiveShareClient, + LiveTimer, + LiveTimerEvents, + ITimerConfig, + } from "@microsoft/live-share"; + import { LiveShareHost } from "@microsoft/teams-js"; + + // Join the Fluid container and create LiveTimer instance + const host = LiveShareHost.create(); + const client = new LiveShareClient(host); + await client.join(); + const timer = await client.getDDS("unique-id", LiveTimer); + + // Register listener for when the timer starts its countdown + timer.on(LiveTimerEvents.started, (config: ITimerConfig, local: boolean) => { + // Update UI to show timer has started + }); + + // Initialize to begin synchronizing timer events + await timer.initialize(); + + // Start a 60 second timer for users in session + await timer.start(1000 * 60); + ``` */ public async start(duration: number): Promise { LiveDataObjectNotInitializedError.assert( @@ -255,6 +340,62 @@ export class LiveTimer extends LiveDataObject<{ * * @throws error if initialization has not yet succeeded. * @throws error if the local user does not have the required roles defined through the `allowedRoles` prop in `.initialize()`. + * + * @example + ```ts + import { + LiveShareClient, + LiveTimer, + LiveTimerEvents, + ITimerConfig, + } from "@microsoft/live-share"; + import { LiveShareHost } from "@microsoft/teams-js"; + + // Join the Fluid container and create LiveTimer instance + const host = LiveShareHost.create(); + const client = new LiveShareClient(host); + await client.join(); + const timer = await client.getDDS("unique-id", LiveTimer); + + // Register listeners for timer changes before initializing + + // Register listener for when the timer starts its countdown + timer.on(LiveTimerEvents.started, (config: ITimerConfig, local: boolean) => { + // Update UI to show timer has started + }); + + // Register listener for when a paused timer has resumed + timer.on(LiveTimerEvents.played, (config: ITimerConfig, local: boolean) => { + // Update UI to show timer has resumed + }); + + // Register listener for when a playing timer has paused + timer.on(LiveTimerEvents.paused, (config: ITimerConfig, local: boolean) => { + // Update UI to show timer has paused + }); + + // Register listener for when a playing timer has finished + timer.on(LiveTimerEvents.finished, (config: ITimerConfig) => { + // Update UI to show timer is finished + }); + + // Register listener for the timer progressed by 20 milliseconds + timer.on(LiveTimerEvents.onTick, (milliRemaining: number) => { + // Update UI to show remaining time + }); + + // Initialize to begin synchronizing timer events + await timer.initialize(); + + // Start a 60 second timer for users in session + await timer.start(1000 * 60); + + // Pause the timer for users in session + await timer.pause(); + + // Resume the timer for users in session + await timer.play(); + ``` */ public async play(): Promise { LiveDataObjectNotInitializedError.assert( @@ -304,6 +445,44 @@ export class LiveTimer extends LiveDataObject<{ * * @throws error if initialization has not yet succeeded. * @throws error if the local user does not have the required roles defined through the `allowedRoles` prop in `.initialize()`. + * + * @example + ```ts + import { + LiveShareClient, + LiveTimer, + LiveTimerEvents, + ITimerConfig, + } from "@microsoft/live-share"; + import { LiveShareHost } from "@microsoft/teams-js"; + + // Join the Fluid container and create LiveTimer instance + const host = LiveShareHost.create(); + const client = new LiveShareClient(host); + await client.join(); + const timer = await client.getDDS("unique-id", LiveTimer); + + // Register listeners for timer changes before initializing + + // Register listener for when the timer starts its countdown + timer.on(LiveTimerEvents.started, (config: ITimerConfig, local: boolean) => { + // Update UI to show timer has started + }); + + // Register listener for when a playing timer has paused + timer.on(LiveTimerEvents.paused, (config: ITimerConfig, local: boolean) => { + // Update UI to show timer has paused + }); + + // Initialize to begin synchronizing timer events + await timer.initialize(); + + // Start a 60 second timer for users in session + await timer.start(1000 * 60); + + // Pause the timer for users in session + await timer.pause(); + ``` */ public async pause(): Promise { LiveDataObjectNotInitializedError.assert( @@ -347,10 +526,7 @@ export class LiveTimer extends LiveDataObject<{ clientId: this._currentConfig.clientId, }; - const isConfigNewer = LiveEvent.isNewer( - currentClientTimestamp, - config - ); + const isConfigNewer = isEventNewer(currentClientTimestamp, config); const currentTime = this.liveRuntime.getTimestamp(); const endTime = this.endTimeFromConfig(config); @@ -462,9 +638,25 @@ export class LiveTimer extends LiveDataObject<{ private endTimeFromConfig(config: ITimerConfigEvent): number { return config.timestamp - config.data.position + config.data.duration; } + + /** + * initializingFirstTime is run only once by the first client to create the DataObject. Here we use it to + * initialize the state of the DataObject. + */ + protected async initializingFirstTime() { + this.debugInfo = `LivePresence-${this.id}`; + } } +export type LiveTimer = LiveTimerClass; + +// eslint-disable-next-line no-redeclare +export const LiveTimer = (() => { + const kind = LiveTimerClass; + return kind as typeof kind & SharedObjectKind; +})(); + /** - * Register `LiveTimer` as an available `LoadableObjectClass` for use in packages that support dynamic object loading, such as `@microsoft/live-share-turbo`. + * Register `LiveTimer` as an available `SharedObjectKind` for use in dynamic object loading. */ DynamicObjectRegistry.registerObjectClass(LiveTimer, LiveTimer.TypeName); diff --git a/packages/live-share/src/LocalTimestampProvider.ts b/packages/live-share/src/LocalTimestampProvider.ts index 0f0af24e6..ad78e4070 100644 --- a/packages/live-share/src/LocalTimestampProvider.ts +++ b/packages/live-share/src/LocalTimestampProvider.ts @@ -3,7 +3,7 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { ITimestampProvider } from "./interfaces"; +import { ITimestampProvider } from "./interfaces.js"; /** * Implements a local timestamp provider for testing purposes. diff --git a/packages/live-share/src/TestLiveShareHost.ts b/packages/live-share/src/TestLiveShareHost.ts index 0a30bbeb9..25a4c4657 100644 --- a/packages/live-share/src/TestLiveShareHost.ts +++ b/packages/live-share/src/TestLiveShareHost.ts @@ -3,6 +3,7 @@ * Licensed under the Microsoft Live Share SDK License. */ +import { ITokenProvider } from "@fluidframework/azure-client"; import { ILiveShareHost, IFluidTenantInfo, @@ -11,7 +12,7 @@ import { ContainerState, UserMeetingRole, IClientInfo, -} from "./interfaces"; +} from "./interfaces.js"; /** * Live Share Host implementation used for local testing. @@ -28,10 +29,12 @@ export class TestLiveShareHost implements ILiveShareHost { * @returns */ public static create( + insecureTokenProvider: ITokenProvider, getLocalTestContainerId?: () => string | undefined, setLocalTestContainerId?: (containerId: string) => void ): ILiveShareHost { return new TestLiveShareHost( + insecureTokenProvider, getLocalTestContainerId, setLocalTestContainerId ); @@ -41,6 +44,7 @@ export class TestLiveShareHost implements ILiveShareHost { * @hidden */ private constructor( + public readonly insecureTokenProvider: ITokenProvider, private _getLocalTestContainerId?: () => string | undefined, private _setLocalTestContainerId?: (containerId: string) => void ) {} diff --git a/packages/live-share/src/TimeInterval.ts b/packages/live-share/src/TimeInterval.ts index 888347faf..815569bd2 100644 --- a/packages/live-share/src/TimeInterval.ts +++ b/packages/live-share/src/TimeInterval.ts @@ -8,25 +8,25 @@ * Manages converting time intervals from seconds-to-milliseconds and vice versa. */ export class TimeInterval { - private _value: number; + protected _milliseconds: number; constructor(defaultMilliseconds: number) { - this._value = defaultMilliseconds; + this._milliseconds = defaultMilliseconds; } public get milliseconds(): number { - return this._value; + return this._milliseconds; } public set milliseconds(value: number) { - this._value = value; + this._milliseconds = value; } public get seconds(): number { - return this._value / 1000; + return this.milliseconds / 1000; } public set seconds(value: number) { - this._value = Math.floor(value * 1000); + this.milliseconds = Math.floor(value * 1000); } } diff --git a/packages/live-share/src/TimestampProvider.ts b/packages/live-share/src/TimestampProvider.ts index 6706a5091..ae75fd1e0 100644 --- a/packages/live-share/src/TimestampProvider.ts +++ b/packages/live-share/src/TimestampProvider.ts @@ -3,7 +3,7 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { ILiveShareHost, INtpTimeInfo, ITimestampProvider } from "./interfaces"; +import { INtpTimeInfo, ITimestampProvider } from "./interfaces.js"; const IMPROVE_ACCURACY_INTERVAL = 5 * 1000; const IMPROVE_ACCURACY_ATTEMPTS = 5; diff --git a/packages/live-share/src/errors.ts b/packages/live-share/src/errors.ts index 146193829..aca86fe55 100644 --- a/packages/live-share/src/errors.ts +++ b/packages/live-share/src/errors.ts @@ -1,5 +1,5 @@ -import { LiveShareReportIssueLink } from "./internals"; -import { LiveDataObjectInitializeState } from "./interfaces"; +import { LiveDataObjectInitializeState } from "./interfaces.js"; +import { LiveShareReportIssueLink } from "./internals/consts.js"; /** * @hidden @@ -76,3 +76,25 @@ export class LiveDataObjectInitializeNotNeededError extends Error { ); } } + +/** + * @hidden + * Use for generic expected errors. Use to get standard formatting of errors. + */ +export class ExpectedError extends Error { + constructor(prefix: string, message: string, helpText: string) { + super( + `${prefix} - ${message}.\n${helpText}\nIf you think you received this error by mistake, report an issue at ${LiveShareReportIssueLink}.` + ); + } + + static assert( + condition: boolean, + prefix: string, + message: string, + helpText: string + ): asserts condition { + if (condition) return; + throw new ExpectedError(prefix, message, helpText); + } +} diff --git a/packages/live-share/src/index.internal.ts b/packages/live-share/src/index.internal.ts new file mode 100644 index 000000000..abdf2face --- /dev/null +++ b/packages/live-share/src/index.internal.ts @@ -0,0 +1,24 @@ +// Exposed for other live share libs, or advanced use cases. +export * from "./internals/BaseLiveShareClient.js"; +export * from "./internals/Deferred.js"; +export * from "./internals/DynamicObjectRegistry.js"; +export * from "./internals/DynamicObjectManager.js"; +export * from "./internals/LiveDataObject.js"; +export * from "./internals/LiveEventScope.js"; +export * from "./internals/LiveEventSource.js"; +export * from "./internals/LiveEventTarget.js"; +export * from "./internals/LiveObjectSynchronizer.js"; +export * from "./internals/LiveShareRuntime.js"; +export * from "./internals/schema-injection-utils.js"; +export * from "./internals/smuggle.js"; + +export { + waitForDelay, + waitUntilConnected, + isNewerEvent as isEventNewer, +} from "./internals/utils.js"; +export { isErrorLike } from "./internals/type-guards.js"; +export { + MockLiveShareRuntime, + MockTokenProvider, +} from "./internals/mock/MockLiveShareRuntime.js"; diff --git a/packages/live-share/src/index.public.ts b/packages/live-share/src/index.public.ts new file mode 100644 index 000000000..f1e7f4e22 --- /dev/null +++ b/packages/live-share/src/index.public.ts @@ -0,0 +1,22 @@ +/*! + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Microsoft Live Share SDK License. + */ + +export * from "./AzureLiveShareClient.js"; +export * from "./AzureLiveShareHost.js"; +export * from "./errors.js"; +export * from "./HostTimestampProvider.js"; +export * from "./interfaces.js"; +export * from "./LiveEvent.js"; +export * from "./LiveFollowMode.js"; +export * from "./LivePresence.js"; +export * from "./LivePresenceUser.js"; +export * from "./LiveShareClient.js"; +export * from "./LiveState.js"; +export * from "./LiveTelemetryLogger.js"; +export * from "./LiveTimer.js"; +export * from "./LocalTimestampProvider.js"; +export * from "./TestLiveShareHost.js"; +export * from "./TimeInterval.js"; +export * from "./TimestampProvider.js"; diff --git a/packages/live-share/src/index.ts b/packages/live-share/src/index.ts deleted file mode 100644 index bc527f7f4..000000000 --- a/packages/live-share/src/index.ts +++ /dev/null @@ -1,30 +0,0 @@ -/*! - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Microsoft Live Share SDK License. - */ - -export * from "./DynamicObjectRegistry"; -export * from "./HostTimestampProvider"; -export * from "./interfaces"; -export * from "./LiveEvent"; -export * from "./LiveEventScope"; -export * from "./LiveEventSource"; -export * from "./LiveEventTarget"; -export * from "./LiveEventTimer"; -export * from "./LivePresence"; -export * from "./LivePresenceUser"; -export * from "./LiveFollowMode"; -export * from "./LiveShareClient"; -export * from "./LiveState"; -export * from "./LiveTelemetryLogger"; -export * from "./LiveTimer"; -export * from "./LocalTimestampProvider"; -export * from "./TestLiveShareHost"; -export * from "./TimeInterval"; -export * from "./TimestampProvider"; -export * from "./schema-injection-utils"; -export * from "./LiveDataObject"; -export * from "./LiveShareRuntime"; -export * from "./AzureLiveShareHost"; -export * from "./LiveObjectSynchronizer"; -export * from "./errors"; diff --git a/packages/live-share/src/interfaces.ts b/packages/live-share/src/interfaces.ts index 00b3f0046..2e596ce86 100644 --- a/packages/live-share/src/interfaces.ts +++ b/packages/live-share/src/interfaces.ts @@ -3,9 +3,9 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { IInboundSignalMessage } from "@fluidframework/runtime-definitions"; +import { IInboundSignalMessage } from "@fluidframework/runtime-definitions/legacy"; import { AzureContainerServices } from "@fluidframework/azure-client"; -import { IFluidContainer } from "fluid-framework"; +import type { IFluidContainer, ContainerSchema } from "fluid-framework"; /** * Base interface for all event objects. @@ -15,6 +15,10 @@ export interface IEvent { * Name of the event. */ name: string; + /** + * Optional. When specified, the signal is only sent to the provided client id. + */ + targetClientId?: string; } /** @@ -277,13 +281,15 @@ export interface ILiveShareHost { } /** - * Response object from `.joinContainer()` in `LiveShareClient` + * Response object from `.join()` in `LiveShareClient` */ -export interface ILiveShareJoinResults { +export interface ILiveShareJoinResults< + TContainerSchema extends ContainerSchema = ContainerSchema, +> { /** * Fluid container */ - container: IFluidContainer; + container: IFluidContainer; /** * Azure Container Services, which includes things like Fluid Audience */ @@ -307,6 +313,7 @@ export interface ILiveShareJoinResults { * just pass `this.context.containerRuntime` to any class that takes an `IContainerRuntimeSignaler`. */ export interface IContainerRuntimeSignaler { + clientId?: string; on( event: "signal", listener: (message: IInboundSignalMessage, local: boolean) => void @@ -315,7 +322,13 @@ export interface IContainerRuntimeSignaler { event: "signal", listener: (message: IInboundSignalMessage, local: boolean) => void ): this; - submitSignal(type: string, content: any): void; + /** + * Submits the signal to be sent to other clients. + * @param type - Type of the signal. + * @param content - Content of the signal. Should be a JSON serializable object or primitive. + * @param targetClientId Optional. When specified, the signal is only sent to the provided client id. + */ + submitSignal(type: string, content: any, targetClientId?: string): void; } /** diff --git a/packages/live-share/src/internals/BackwardsCompatibilityHostDecorator.ts b/packages/live-share/src/internals/BackwardsCompatibilityHostDecorator.ts deleted file mode 100644 index 111b71e67..000000000 --- a/packages/live-share/src/internals/BackwardsCompatibilityHostDecorator.ts +++ /dev/null @@ -1,206 +0,0 @@ -/*! - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Microsoft Live Share SDK License. - */ - -import { ILiveShareHost, UserMeetingRole, IClientInfo } from "../interfaces"; -import { BaseHostDecorator } from "./BaseHostDecorator"; -import { RequestCache } from "./RequestCache"; -import { - isErrorLike, - isMobileWorkaroundRolesResponse, - isClientRolesResponse, -} from "./type-guards"; -import { waitForResult } from "./utils"; - -const EXPONENTIAL_BACKOFF_SCHEDULE = [100, 200, 200, 400, 600]; -const CACHE_LIFETIME = 5 * 60 * 1000; // original cache time - -/** - * @hidden - * Optionally Adds `retrySchedule` to `getClientInfo`. doesn't break `ILiveShareHost` interface. - * - * For internal use only. Will be deleted. - */ -export interface BackwardsCompatibilityGetClientInfoRetrySchedule { - getClientInfo( - clientId: string, - lateFinish?: () => void, - retrySchedule?: number[] - ): Promise; -} - -/** - * @hidden - * Decorator that provides backwards compatibility for getClientInfo - * If getClientInfo does not exist on an unsupported client, `IUserInfo.displayName` will be undefined - * - * For internal use only. Will be deleted. - */ -export class BackwardsCompatibilityHostDecorator extends BaseHostDecorator { - private readonly _userRolesRequestCache: RequestCache = - new RequestCache(CACHE_LIFETIME); - - private _totalTries = 4; - private _getClientInfoTriesRemaining = this._totalTries; - private _getClientInfoExists = false; - private _hasWarnedPolyfill = false; - - /** - * @hidden - * _host would be `BackwardsCompatibilityHostDecorator` decorator: `new BackwardsCompatibilityHostDecorator(new LiveShareHostDecorator(teamsJsHost))` - */ - constructor( - readonly _host: ILiveShareHost & - BackwardsCompatibilityGetClientInfoRetrySchedule - ) { - super(_host); - this.warmupCheckGetClientInfoExists(); - } - - /** - * @deprecated - */ - public async getClientRoles( - clientId: string - ): Promise { - if (!clientId) { - throw new Error( - `BackwardsCompatibilityHostDecorator: called getClientInfo() without a clientId` - ); - } - return this._userRolesRequestCache.cacheRequest(clientId, () => { - return waitForResult( - async () => { - return await this._host.getClientRoles(clientId); - }, - (result) => { - if (isClientRolesResponse(result)) { - return { - response: result, - }; - } else if (isMobileWorkaroundRolesResponse(result)) { - return { - response: result.userRoles, - }; - } - return null; - }, - () => { - return new Error( - `BackwardsCompatibilityHostDecorator: timed out getting roles for a remote client ID` - ); - }, - EXPONENTIAL_BACKOFF_SCHEDULE - ); - }); - } - - public async getClientInfo( - clientId: string - ): Promise { - // 1. fire getClientInfo and getClientRoles at same time. - // - on new versions of teams client getClientInfo and getClientRoles share same network cache, cheap to call. - // - on old versions of teams client getClientRoles needs to be called anyway. - - // 2. if getClientInfo resolves, return that - // 3. if getClientInfo times out, return polyfil using getClientRoles, log warning - // 4. if getClientInfo times out after multiple calls, start using only polyfill. - - if (this._getClientInfoExists) { - return await this._host.getClientInfo(clientId); - } - - if (this._getClientInfoTriesRemaining <= 0) { - if (!this._hasWarnedPolyfill) { - console.warn( - "BackwardsCompatibilityHostDecorator.getClientInfo: using getClientInfo polyfill" - ); - this._hasWarnedPolyfill = true; - } - const roles = await this.getClientRoles(clientId); - return { - userId: clientId, - displayName: undefined, - roles: roles ?? [], - }; - } - - const getClientRoles = this.getClientRoles(clientId); - try { - const clientInfo = await this._host.getClientInfo( - clientId, - () => { - // The request initially timed out, but then it later was rejected/resolved for a legitimate reason - this._getClientInfoExists = true; - }, - this.getRetrySchedule() - ); - this._getClientInfoExists = true; - return clientInfo; - } catch (error: unknown) { - if (isErrorLike(error) && error.message.includes("timed out")) { - this._getClientInfoTriesRemaining--; - if (this._getClientInfoTriesRemaining <= 0) { - console.warn( - "BackwardsCompatibilityHostDecorator.getClientInfo: will use getClientInfo polyfill" - ); - } - - const roles = await getClientRoles; - return { - userId: clientId, - displayName: undefined, - roles: roles ?? [], - }; - } - } - this._getClientInfoExists = true; - // retry schedule gets longer as we lose confidence it exists. - // First call to this._host.getClientInfo may result in an error if the api exists, but without retries. - // If error we know the api exists. call the normal implementation again. - // this should only ever be hit one time at the start because this._getClientInfoExists will be true. - console.log( - "BackwardsCompatibilityHostDecorator: error, retryingWithActual" - ); - return await this.getClientInfo(clientId); - } - - private warmupCheckGetClientInfoExists() { - if (this._getClientInfoExists) return; - - // warmup doesn't use polyfill implementation - // "fakeId" clientId, error expected, hopefully not a timeout - this._host - .getClientInfo( - "fakeId", - () => { - // The request initially timed out, but then it later was rejected/resolved for a legitimate reason - this._getClientInfoExists = true; - }, - [] - ) - .catch((e) => { - if (e.message.includes("timed out")) { - this._getClientInfoTriesRemaining--; - if (this._getClientInfoTriesRemaining > 0) { - this.warmupCheckGetClientInfoExists(); - } else { - console.warn( - "BackwardsCompatibilityHostDecorator.getClientInfo: will use getClientInfo polyfill" - ); - } - } else { - // resolved for reason other than timeout, api exists - this._getClientInfoExists = true; - } - }); - } - - // retry little bit longer when getting to end of retries remaining. - private getRetrySchedule(): number[] { - const retryAmount = - this._totalTries - Math.max(0, this._getClientInfoTriesRemaining); - return EXPONENTIAL_BACKOFF_SCHEDULE.slice(0, retryAmount); - } -} diff --git a/packages/live-share/src/internals/BaseHostDecorator.ts b/packages/live-share/src/internals/BaseHostDecorator.ts index 8b15aca77..21363f8f5 100644 --- a/packages/live-share/src/internals/BaseHostDecorator.ts +++ b/packages/live-share/src/internals/BaseHostDecorator.ts @@ -5,7 +5,7 @@ import { INtpTimeInfo, UserMeetingRole, IClientInfo, -} from "../interfaces"; +} from "../interfaces.js"; export class BaseHostDecorator implements ILiveShareHost { /** diff --git a/packages/live-share/src/internals/BaseLiveShareClient.ts b/packages/live-share/src/internals/BaseLiveShareClient.ts new file mode 100644 index 000000000..841926962 --- /dev/null +++ b/packages/live-share/src/internals/BaseLiveShareClient.ts @@ -0,0 +1,273 @@ +/*! + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Microsoft Live Share SDK License. + */ + +import { + ContainerSchema, + FluidObject, + IFluidContainer, + SharedObjectKind, +} from "fluid-framework"; +import { SharedMap } from "fluid-framework/legacy"; +import { AzureContainerServices } from "@fluidframework/azure-client"; +import { IFluidLoadable } from "@fluidframework/core-interfaces"; +import { DynamicObjectRegistry } from "./DynamicObjectRegistry.js"; +import { DynamicObjectManager } from "./DynamicObjectManager.js"; +import { LiveShareRuntime } from "./LiveShareRuntime.js"; +import { + getRootDataObject, + getContainerRuntime, + getRootDirectory, + TurboDirectory, + TurboDynamicObjects, + TurboStateMap, +} from "./smuggle.js"; +import { getFactoryName } from "./fluid-duplicated.js"; +import { ExpectedError } from "../errors.js"; + +/** + * Base class for building Fluid Turbo clients. + * @remarks + * Unlike other Fluid clients, the turbo client wraps functionality regularly exposed through an `IFluidContainer`. This is due to the more opinionated + * nature of this package than vanilla Fluid Framework, where developers do not define a full `ContainerSchema` themselves and objects are loaded dynamically. + */ +export abstract class BaseLiveShareClient { + private _awaitConnectedPromise?: Promise; + protected _runtime: LiveShareRuntime; + private _turboStateMap?: SharedMap; + private _turboDynamicObjects?: DynamicObjectManager; + + /** + * Constructor to create a new BaseLiveShareClient instance. + * + * @param runtime Live Share runtime instance + */ + protected constructor(runtime: LiveShareRuntime) { + this._runtime = runtime; + } + + /** + * Get the Fluid join container results. + * Includes Fluid container and Azure container services. + */ + public abstract get results(): + | { + container: IFluidContainer; + services: AzureContainerServices; + } + | undefined; + + /** + * Default SharedMap included in all clients for the purposes of tracking simple app state + */ + public get stateMap(): SharedMap | undefined { + if (this._turboStateMap) { + return this._turboStateMap; + } + return undefined; + } + + /** + * Join container functions to call. Used for generating helpful error messages when calling {@link getDDS}. + */ + protected abstract getDDSErrorJoinFunctionText: string; + + /** + * Setting for whether `LiveDataObject` instances using `LiveObjectSynchronizer` can send background updates. + * Default value is `true`. + * + * @remarks + * This is useful for scenarios where there are a large number of participants in a session, since service performance degrades as more socket connections are opened. + * Intended for use when a small number of users are intended to be "in control", such as the `LiveFollowMode` class's `startPresenting()` feature. + * There should always be at least one user in the session that has `canSendBackgroundUpdates` set to true. + * Set to true when the user is eligible to send background updates (e.g., "in control"), or false when that user is not in control. + * This setting will not prevent the local user from explicitly changing the state of objects using `LiveObjectSynchronizer`, such as `.set()` in `LiveState`. + * Impacts background updates of `LiveState`, `LivePresence`, `LiveTimer`, and `LiveFollowMode`. + */ + public get canSendBackgroundUpdates(): boolean { + return this._runtime.canSendBackgroundUpdates; + } + + public set canSendBackgroundUpdates(value: boolean) { + this._runtime.canSendBackgroundUpdates = value; + } + + private async dynamicObjects(): Promise { + if (!this._turboDynamicObjects) { + await this.loadFromTurboDirectory(); + } + return this._turboDynamicObjects; + } + + private async loadFromTurboDirectory() { + if (!this.results) { + return; + } + + const rootDataObject = getRootDataObject(this.results.container); + const rootDirectory = getRootDirectory(rootDataObject); + const turboDir = rootDirectory.getSubDirectory(TurboDirectory); + + if (turboDir) { + this._turboDynamicObjects = await turboDir + .get(TurboDynamicObjects) + .get(); + this._turboStateMap = await turboDir.get(TurboStateMap).get(); + } + } + + /** + * Callback to load a Fluid DDS for a given key. If the object does not already exist, a new one will be created. + * If the key matches an object in the `initialObjects` from your `ContainerSchema`, the initial object will be returned. + * + * @template T Type of Fluid object to load. + * @param objectKey unique key for the Fluid DDS you'd like to load + * @param objectClass Fluid SharedObjectKind you'd like to load of type T + * @param onDidFirstInitialize Optional. Callback that is used when the object was initially created. + * @returns DDS object corresponding to `objectKey` + * + * @throws error if you have not already joined the Fluid container. + * @throws error if you are using a legacy container created prior to Live Share version 2.0.0 or greater. + * + * @example + ```ts + import { LiveShareClient, LivePresence } from "@microsoft/live-share"; + import { LiveShareHost } from "@microsoft/teams-js"; + + // Join the Fluid container + const host = LiveShareHost.create(); + const client = new LiveShareClient(host); + await client.join(); + // Create a LivePresence instance + const presence = await client.getDDS("unique-id", LivePresence, (dds) => { + console.log("first created dds", dds); + }); + ``` + */ + public async getDDS< + T extends IFluidLoadable = FluidObject & IFluidLoadable, + >( + objectKey: string, + objectClass: SharedObjectKind, + onDidFirstInitialize?: (dds: T) => void + ): Promise { + ExpectedError.assert( + !!this.results, + "BaseLiveShareClient:getDDS", + "cannot call until successfully joined a FluidContainer", + `To fix this issue, call the ${this.getDDSErrorJoinFunctionText} function before using this API.` + ); + + await this.waitUntilConnected(); + try { + const initialDDS = this.results.container.initialObjects[ + objectKey + ] as T | undefined; + if (initialDDS !== undefined) { + return initialDDS; + } + } catch (e) { + // ignore "Initial Objects were not correctly initialized" error if none defined. + } + + const dynamicObjects = await this.dynamicObjects(); + ExpectedError.assert( + !!dynamicObjects, + "BaseLiveShareClient:getDDS", + "getDDS must have valid dynamicObjects DynamicObjectManager instance. This implies this container was created with a version of Live Share prior to 2.0.0 or greater.", + "To fix this error, please create a new Fluid container and try again." + ); + + // The uniqueKey key makes the developer provided uniqueKey never conflict across different DDS objects + const className = + (objectClass as any).name ?? + getFactoryName(objectClass) ?? + "unknown"; + const uniqueKey = `<${className}>:${objectKey}`; + const response = await dynamicObjects.getDDS( + uniqueKey, + objectClass, + this.results.container, + onDidFirstInitialize + ); + return response.dds; + } + + /** + * Get the container schema to use within a `BaseLiveShareClient` container. + * + * @param initialObjects Optional. Initial objects to add to the schema + * @returns a `ContainerSchema` record to use in a Fluid container + */ + protected getContainerSchema< + const TContainerSchema extends ContainerSchema, + >(schema?: TContainerSchema): TContainerSchema { + return { + initialObjects: { + ...schema?.initialObjects, + }, + // Get the static registry of SharedObjectKind types. + dynamicObjectTypes: [ + ...(schema?.dynamicObjectTypes ?? []), + ...DynamicObjectRegistry.dynamicLoadableObjects.values(), + ], + } as TContainerSchema /* and added the dynamic object types */; + } + + /** + * Utility function to wait until the Fluid container is connected. + * + * @returns promise that will resolve once the container connects. + */ + protected async waitUntilConnected(): Promise { + if (this._awaitConnectedPromise) { + return this._awaitConnectedPromise; + } + this._awaitConnectedPromise = new Promise((resolve, reject) => { + if (!this.results?.container) { + reject( + new Error( + "FluidTurboClient awaitConnected: cannot load DDS without a Fluid container" + ) + ); + this._awaitConnectedPromise = undefined; + } else { + const onConnected = () => { + this.results?.container.off("connected", onConnected); + resolve(); + }; + // Wait until connected event to ensure we have the latest document + // and don't accidentally override a dds handle recently created + // by another client + if (this.results.container.connectionState === 2) { + resolve(); + } else { + this.results.container.on("connected", onConnected); + } + } + }); + return this._awaitConnectedPromise; + } + + /** + * @internal + * Adds additional objects needed by Live Share to the Fluid container's root data object. + * Intended for use only when extending `BaseLiveShareClient`. + * This should be called only when the container is first created. + * + * @param container Fluid container to add the objects to. + */ + protected async addTurboFolder(container: IFluidContainer) { + const rootDataObject = getRootDataObject(container); + const rootDirectory = getRootDirectory(rootDataObject); + const containerRuntime = getContainerRuntime(rootDataObject); + + const turboDir = rootDirectory.createSubDirectory(TurboDirectory); + const obj = await SharedMap.create(containerRuntime, undefined); + turboDir.set(TurboStateMap, obj.handle); + + const turboObjectManager = await container.create(DynamicObjectManager); + turboDir.set(TurboDynamicObjects, turboObjectManager.handle); + } +} diff --git a/packages/live-share/src/internals/ContainerSynchronizer.ts b/packages/live-share/src/internals/ContainerSynchronizer.ts index 04b150cd4..a5031be6c 100644 --- a/packages/live-share/src/internals/ContainerSynchronizer.ts +++ b/packages/live-share/src/internals/ContainerSynchronizer.ts @@ -1,14 +1,14 @@ -import { IRuntimeSignaler } from "../LiveEventScope"; -import { LiveShareRuntime } from "../LiveShareRuntime"; -import { IContainerRuntimeSignaler, ILiveEvent } from "../interfaces"; +import { IRuntimeSignaler } from "./LiveEventScope.js"; +import { LiveShareRuntime } from "./LiveShareRuntime.js"; +import { IContainerRuntimeSignaler, ILiveEvent } from "../interfaces.js"; import { GetAndUpdateStateHandlers, StateSyncEventContent, -} from "./internal-interfaces"; -import { ThrottledEventQueue } from "./ThrottledEventQueue"; -import { LiveObjectManager } from "./LiveObjectManager"; -import { ObjectSynchronizerEvents } from "./consts"; -import { waitUntilConnected } from "./utils"; +} from "./internal-interfaces.js"; +import { ThrottledEventQueue } from "./ThrottledEventQueue.js"; +import { LiveObjectManager } from "./LiveObjectManager.js"; +import { ObjectSynchronizerEvents } from "./consts.js"; +import { waitUntilConnected } from "./utils.js"; /** * @hidden @@ -21,7 +21,7 @@ export class ContainerSynchronizer { private _throttledEventsQueue: ThrottledEventQueue = new ThrottledEventQueue(this); private _connectedKeys: string[] = []; - private _hTimer: NodeJS.Timeout | undefined; + private _hTimer?: any; private _connectSentForClientId?: string; private _onBoundConnectedListener?: (clientId: string) => Promise; private _onReceiveObjectUpdateListener?: ( @@ -110,15 +110,20 @@ export class ContainerSynchronizer { /** * On send background updates handler * + * @param targetClientId Optional. When specified, the signal is only sent to the provided client id. + * * @returns void promise once the events were sent (unless skipped) */ - public async onSendBackgroundUpdates(): Promise { + public async onSendBackgroundUpdates( + targetClientId?: string + ): Promise { if (!this._liveRuntime.canSendBackgroundUpdates) return; await this.sendGroupEvent( this._connectedKeys.filter((key) => this._ddsBackgroundUpdateEnabled.has(key) ), - ObjectSynchronizerEvents.update + ObjectSynchronizerEvents.update, + targetClientId ).catch((err) => console.error(err)); } @@ -199,11 +204,13 @@ export class ContainerSynchronizer { * Send a batch of events * @param updates updates to send * @param evtType type of event + * @param targetClientId Optional. When specified, the signal is only sent to the provided client id. * @returns event where data is then StateSyncEventContent containing the batched events that were sent. */ public async sendEventUpdates( updates: StateSyncEventContent, - evtType: string + evtType: string, + targetClientId?: string ): Promise | undefined> { const updateKeys = Object.keys(updates); // Send event if we have any updates to broadcast @@ -218,7 +225,11 @@ export class ContainerSynchronizer { : this._liveRuntime.getTimestamp(), name: evtType, }; - this._containerRuntime.submitSignal(evtType, content); + this._containerRuntime.submitSignal( + evtType, + content, + targetClientId + ); return content; } } @@ -264,7 +275,8 @@ export class ContainerSynchronizer { private async sendGroupEvent( keys: string[], - evtType: string + evtType: string, + targetClientId?: string ): Promise<{ sent: string[]; skipped: string[]; @@ -296,9 +308,9 @@ export class ContainerSynchronizer { handlers.shouldUpdateTimestampPeriodically ? this._liveRuntime.getTimestamp() : evtType === - ObjectSynchronizerEvents.connect - ? 0 - : state.timestamp, + ObjectSynchronizerEvents.connect + ? 0 + : state.timestamp, }; continue; } @@ -314,7 +326,7 @@ export class ContainerSynchronizer { const updateKeys = Object.keys(updates); // Send event if we have any updates to broadcast // - `send` is only set if at least one component returns an update. - await this.sendEventUpdates(updates, evtType); + await this.sendEventUpdates(updates, evtType, targetClientId); return { sent: updateKeys, skipped: skipKeys, diff --git a/packages/live-share-turbo/src/dds-objects/DynamicObjectManager.ts b/packages/live-share/src/internals/DynamicObjectManager.ts similarity index 78% rename from packages/live-share-turbo/src/dds-objects/DynamicObjectManager.ts rename to packages/live-share/src/internals/DynamicObjectManager.ts index ed3cd66da..5eb510654 100644 --- a/packages/live-share-turbo/src/dds-objects/DynamicObjectManager.ts +++ b/packages/live-share/src/internals/DynamicObjectManager.ts @@ -3,16 +3,17 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { DataObject, DataObjectFactory } from "@fluidframework/aqueduct"; -import { LoadableObjectClass, IFluidContainer } from "fluid-framework"; +import { DataObjectFactory } from "@fluidframework/aqueduct/legacy"; import { - IFluidHandle, FluidObject, - IFluidLoadable, -} from "@fluidframework/core-interfaces"; -import { assert } from "@fluidframework/common-utils"; -import { ConsensusRegisterCollection } from "@fluidframework/register-collection"; -import { DynamicObjectRegistry, LiveDataObject } from "@microsoft/live-share"; + IFluidContainer, + SharedObjectKind, +} from "fluid-framework"; +import { IFluidHandle, IFluidLoadable } from "@fluidframework/core-interfaces"; +import { ConsensusRegisterCollection } from "@fluidframework/register-collection/legacy"; +import { DynamicObjectRegistry } from "./DynamicObjectRegistry.js"; +import { LiveDataObject } from "./LiveDataObject.js"; +import { UnexpectedError } from "../errors.js"; // Register ConsensusRegisterCollection DynamicObjectRegistry.registerObjectClass( @@ -21,14 +22,14 @@ DynamicObjectRegistry.registerObjectClass( ); type DynamicObjectsCollection = ConsensusRegisterCollection>; -const dynamicObjectsCollectionKey = "<>"; +const dynamicObjectsCollectionKey = "liveShareConsensusRegisterCollectionKey"; /** * Fluid DataObject used in `FluidTurboClient` for the purposes of dynamically loading DDSes. * @remarks * If a DDS does not yet exist for a given key, a new one is created. Fluid `ConsensusRegisterCollection` is used to ensure that only one person will create the DDS. */ -export class DynamicObjectManager extends LiveDataObject { +export class DynamicObjectManagerClass extends LiveDataObject { /** * ConsensusRegisterCollection instance that stores handles for a given key using FWW. */ @@ -48,8 +49,8 @@ export class DynamicObjectManager extends LiveDataObject { * The objects fluid type factory. */ public static readonly factory = new DataObjectFactory( - DynamicObjectManager.TypeName, - DynamicObjectManager, + DynamicObjectManagerClass.TypeName, + DynamicObjectManagerClass, [ConsensusRegisterCollection.getFactory()], {} ); @@ -89,8 +90,9 @@ export class DynamicObjectManager extends LiveDataObject { * never be undefined after `initializingFirstTime`. */ private get dynamicObjectsCollection() { - assert( + UnexpectedError.assert( this._dynamicObjectsCollection !== undefined, + "DynamicObjectManager:dynamicObjectsCollection", "_dynamicObjectsCollection not initialized" ); return this._dynamicObjectsCollection; @@ -101,16 +103,18 @@ export class DynamicObjectManager extends LiveDataObject { * * @template T Type of Fluid object to load. * @param key unique key for the dynamic object - * @param loadableClass the Fluid LoadableObjectClass + * @param objectClass the Fluid SharedObjectKind * @param container Fluid container to load the DDS into + * @param onDidFirstInitialize Optional. Callback that is used when the object was initially created, regardless of whether it is confirmed via consensus or not. * @returns the DDS and whether or not it was created locally */ public async getDDS< - T extends IFluidLoadable = FluidObject & IFluidLoadable + T extends IFluidLoadable = FluidObject & IFluidLoadable, >( key: string, - loadableClass: LoadableObjectClass, - container: IFluidContainer + objectClass: SharedObjectKind, + container: IFluidContainer, + onDidFirstInitialize?: (dds: T) => void ): Promise<{ dds: T; created: boolean; @@ -125,9 +129,10 @@ export class DynamicObjectManager extends LiveDataObject { } // Create a new DDS to attempt to store it into consensusRegisterCollection. The localDDS may not be used if it has first been written by another client. // Fluid's garbage collector will clean up the DDS if it is not used. - const localDDS = await container.create(loadableClass); + const localDDS = await container.create(objectClass); + onDidFirstInitialize?.(localDDS); // Get the DDS with consensus - return this.loadDDSWithConsensus(key, localDDS); + return this.loadDDSWithConsensus(key, localDDS); } /** @@ -137,7 +142,7 @@ export class DynamicObjectManager extends LiveDataObject { * @returns existing DDS in the _dynamicObjectsMap or undefined if it does not exist */ private async internalGetDDS< - T extends FluidObject = FluidObject & IFluidLoadable + T extends FluidObject = FluidObject & IFluidLoadable, >(key: string): Promise { // Check if we already have the DDS / get DDS promise in memory const ddsInMemory = this._dynamicObjectsMap.get(key); @@ -163,7 +168,7 @@ export class DynamicObjectManager extends LiveDataObject { * @returns the DDS and whether or not it was created locally */ private async loadDDSWithConsensus< - T extends IFluidLoadable = FluidObject & IFluidLoadable + T extends IFluidLoadable = FluidObject & IFluidLoadable, >( key: string, localDDS: T @@ -195,6 +200,22 @@ export class DynamicObjectManager extends LiveDataObject { }; } // Fluid did not acknowledge the write, either because the container disconnected or someone else created the object already, so we need to try again - return await this.loadDDSWithConsensus(key, localDDS); + return await this.loadDDSWithConsensus(key, localDDS); } } + +export type DynamicObjectManager = DynamicObjectManagerClass; + +// eslint-disable-next-line no-redeclare +export const DynamicObjectManager = (() => { + const kind = DynamicObjectManagerClass; + return kind as typeof kind & SharedObjectKind; +})(); + +/** + * Register `DynamicObjectManager` as an available `SharedObjectKind` for use in packages that support dynamic object loading, such as `@microsoft/live-share`. + */ +DynamicObjectRegistry.registerObjectClass( + DynamicObjectManager, + DynamicObjectManager.TypeName +); diff --git a/packages/live-share/src/DynamicObjectRegistry.ts b/packages/live-share/src/internals/DynamicObjectRegistry.ts similarity index 58% rename from packages/live-share/src/DynamicObjectRegistry.ts rename to packages/live-share/src/internals/DynamicObjectRegistry.ts index fabc5e355..a836ba5df 100644 --- a/packages/live-share/src/DynamicObjectRegistry.ts +++ b/packages/live-share/src/internals/DynamicObjectRegistry.ts @@ -3,12 +3,11 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { - LoadableObjectClass, - SharedMap, - SharedString, - SharedDirectory, -} from "fluid-framework"; +import { ITree, SharedObjectKind, SharedTree } from "fluid-framework"; +import { SharedMap } from "fluid-framework/legacy"; +import { SharedDirectory } from "@fluidframework/map/legacy"; +import { SharedString } from "@fluidframework/sequence/legacy"; +import type { ISharedObjectKind } from "@fluidframework/shared-object-base/legacy"; /** * Key for window global reference to loadable objects. @@ -19,31 +18,25 @@ import { const GLOBAL_WINDOW_KEY = "@microsoft/live-share:DYNAMIC-LOADABLE-OBJECTS"; /** - * Static registry class for loadable projects for use in frameworks like `@microsoft/live-share-turbo`. All Live Share packages and extension - * frameworks (e.g., `LiveMediaSession` in our media package) will register their classes from within their main files. Goal of this class is for - * all Live Share packages that a developer has installed will be registered as available dynamic objects without the core package needing to be - * aware of what every DDS is. + * Static registry class for loadable objects. All Live Share packages and extension frameworks (e.g., `LiveMediaSession` in our media package) + * will register their classes from within their main files. Goal of this class is for all Live Share packages that a developer has installed + * will be registered as available dynamic objects without the core package needing to be aware of what every DDS is. */ export class DynamicObjectRegistry { - private static _dynamicLoadableObjects: Map< - string, - LoadableObjectClass - > = new Map>(); + private static _dynamicLoadableObjects: Map> = + new Map>(); /** * Get all registered dynamic loadable objects */ public static get dynamicLoadableObjects(): Map< string, - LoadableObjectClass + SharedObjectKind > { if (typeof window === "undefined") { return this._dynamicLoadableObjects; } return ((window as any)[GLOBAL_WINDOW_KEY] || - this._dynamicLoadableObjects) as Map< - string, - LoadableObjectClass - >; + this._dynamicLoadableObjects) as Map>; } /** @@ -52,15 +45,15 @@ export class DynamicObjectRegistry { * @remarks * Duplicate classes will be ignored. * - * @param loadableObjectClass the Fluid loadable object class to register + * @param objectKind the Fluid loadable object class to register */ public static registerObjectClass( - loadableObjectClass: LoadableObjectClass, + objectClass: SharedObjectKind, typeName: string ) { const loadableObjects = this.dynamicLoadableObjects; if (loadableObjects.has(typeName)) return; - loadableObjects.set(typeName, loadableObjectClass); + loadableObjects.set(typeName, objectClass); if (typeof window !== "undefined") { (window as any)[GLOBAL_WINDOW_KEY] = loadableObjects; } @@ -83,3 +76,10 @@ DynamicObjectRegistry.registerObjectClass( SharedDirectory, SharedDirectory.getFactory().type ); +DynamicObjectRegistry.registerObjectClass( + SharedTree, + ( + SharedTree as unknown as ISharedObjectKind & + SharedObjectKind + ).getFactory().type +); diff --git a/packages/live-share/src/internals/FormatFixHostDecorator.ts b/packages/live-share/src/internals/FormatFixHostDecorator.ts deleted file mode 100644 index 7c376382d..000000000 --- a/packages/live-share/src/internals/FormatFixHostDecorator.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { UserMeetingRole, IClientInfo } from "../interfaces"; -import { BaseHostDecorator } from "./BaseHostDecorator"; - -import { isClientRolesResponse, isIClientInfo } from "./type-guards"; - -/** - * @hidden - * Temporary fix for android bug which causes IClientInfo to come back with the keys modified - * Delete in November 2023 - */ -export class FormatFixHostDecorator extends BaseHostDecorator { - public async getClientInfo( - clientId: string - ): Promise { - const clientInfo = await this._host.getClientInfo(clientId); - if (isIClientInfo(clientId)) { - return clientInfo; - } - - const androidBugToClientInfo = androidBugFormatToClientInfo(clientInfo); - if (androidBugToClientInfo) { - return androidBugToClientInfo; - } - return clientInfo; - } -} - -/** - * @hidden - */ -function androidBugFormatToClientInfo(value: any): IClientInfo | undefined { - if (value instanceof Object) { - let userId: string | undefined; - let roles: UserMeetingRole[] | undefined; - let displayName: string | undefined; - Object.keys(value) - .map((key) => value[key]) - .forEach((objectValue) => { - if (isClientRolesResponse(objectValue)) { - roles = objectValue; - } else if (isGuid(objectValue)) { - userId = objectValue; - } else if (typeof objectValue === "string") { - displayName = objectValue; - } - }); - - if (userId && roles) { - return { - userId, - roles, - displayName, - }; - } - } - - return undefined; -} - -function isGuid(value: any) { - if (typeof value === "string") { - let regex: RegExp = - /[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/; - return regex.test(value); - } - - return false; -} diff --git a/packages/live-share/src/LiveDataObject.ts b/packages/live-share/src/internals/LiveDataObject.ts similarity index 80% rename from packages/live-share/src/LiveDataObject.ts rename to packages/live-share/src/internals/LiveDataObject.ts index efdaa5b5e..2b56fc189 100644 --- a/packages/live-share/src/LiveDataObject.ts +++ b/packages/live-share/src/internals/LiveDataObject.ts @@ -2,21 +2,22 @@ import { DataObject, DataObjectTypes, IDataObjectProps, -} from "@fluidframework/aqueduct"; -import { LiveShareRuntime } from "./LiveShareRuntime"; -import { assert } from "@fluidframework/common-utils"; +} from "@fluidframework/aqueduct/legacy"; +import { LiveShareRuntime } from "./LiveShareRuntime.js"; import { IClientInfo, LiveDataObjectInitializeState, UserMeetingRole, -} from "./interfaces"; -import { LiveShareReportIssueLink, waitUntilConnected } from "./internals"; +} from "../interfaces.js"; +import { LiveShareReportIssueLink } from "./consts.js"; +import { waitUntilConnected } from "./utils.js"; +import { UnexpectedError } from "../errors.js"; /** * Extends Fluid's DataObject class. Intended for use with Live Share custom DDS's that rely on a `ILiveShareHost`. */ export abstract class LiveDataObject< - I extends DataObjectTypes = DataObjectTypes + I extends DataObjectTypes = DataObjectTypes, > extends DataObject { /** * @hidden @@ -36,6 +37,11 @@ export abstract class LiveDataObject< */ private _liveRuntime: LiveShareRuntime | null = null; + /** + * @hidden + */ + protected debugInfo = ""; + /** * @internal * `LiveShareRuntime` instance @@ -43,9 +49,10 @@ export abstract class LiveDataObject< * You should usually not set this value to a DDS after calling `.initialize()`, but there is nothing preventing it. */ protected get liveRuntime(): LiveShareRuntime { - assert( + UnexpectedError.assert( this._liveRuntime !== null, - `LiveShareRuntime not initialized. Ensure your Fluid \`ContainerSchema\` was first wrapped inside of \`getLiveContainerSchema()\` before calling \`client.getContainer()\` / \`client.createContainer()\` from your \`AzureClient\` (or equivalent) instance.\nAlternatively, you can use the \`.joinContainer()\` in \`LiveShareClient\`, which does this for you.\nIf you are using \`LiveShareClient\` and are still encountering this issue, please report this issue at ${LiveShareReportIssueLink}.` + `LiveDataObject:liveRuntime:${this.debugInfo}`, + `LiveShareRuntime not initialized. Ensure your Fluid \`ContainerSchema\` was first wrapped inside of \`getLiveContainerSchema()\` before calling \`client.getContainer()\` / \`client.createContainer()\` from your \`AzureClient\` (or equivalent) instance.\nAlternatively, you can use the \`.join()\` in \`LiveShareClient\`, which does this for you.\nIf you are using \`LiveShareClient\` and are still encountering this issue, please report this issue at ${LiveShareReportIssueLink}.` ); return this._liveRuntime; } @@ -76,8 +83,16 @@ export abstract class LiveDataObject< public constructor(props: IDataObjectProps) { super(props); + this.runtime.once("dispose", () => { + this.dispose(); + }); } + /** + * Disposes of the object when its container is disposed of. + */ + public dispose(): void {} + /** * Get the client info for a given clientId * @param clientId Fluid clientId we are requesting user info for diff --git a/packages/live-share/src/LiveEventScope.ts b/packages/live-share/src/internals/LiveEventScope.ts similarity index 67% rename from packages/live-share/src/LiveEventScope.ts rename to packages/live-share/src/internals/LiveEventScope.ts index cb4a4c241..f4ad63618 100644 --- a/packages/live-share/src/LiveEventScope.ts +++ b/packages/live-share/src/internals/LiveEventScope.ts @@ -3,16 +3,18 @@ * Licensed under the Microsoft Live Share SDK License. */ -import EventEmitter from "events"; import { IErrorEvent, - ITelemetryLogger, -} from "@fluidframework/common-definitions"; -import { TypedEventEmitter } from "@fluidframework/common-utils"; -import { IInboundSignalMessage } from "@fluidframework/runtime-definitions"; -import { ILiveEvent, UserMeetingRole } from "./interfaces"; -import { LiveShareRuntime } from "./LiveShareRuntime"; -import { waitUntilConnected } from "./internals"; + ITelemetryBaseLogger, +} from "@fluidframework/core-interfaces"; +import { TypedEventEmitter } from "@fluid-internal/client-utils"; +import { IInboundSignalMessage } from "@fluidframework/runtime-definitions/legacy"; +import { ILiveEvent, UserMeetingRole } from "../interfaces.js"; +import { LiveShareRuntime } from "./LiveShareRuntime.js"; +import { IEvent } from "@fluidframework/core-interfaces"; +import { LiveTelemetryLogger } from "../LiveTelemetryLogger.js"; +import { isILiveEvent } from "./type-guards.js"; +import { waitUntilConnected } from "./utils.js"; /** * Live event callback. @@ -32,14 +34,45 @@ export type LiveEventListener = ( export interface IRuntimeSignaler { readonly clientId: string | undefined; readonly connected: boolean; - readonly logger: ITelemetryLogger; + readonly logger: ITelemetryBaseLogger; on(event: "connected", listener: (clientId: string) => void): this; off(event: "connected", listener: (clientId: string) => void): this; on( event: "signal", listener: (message: IInboundSignalMessage, local: boolean) => void ): this; - submitSignal(type: string, content: any): void; + /** + * Submits the signal to be sent to other clients. + * @param type Type of the signal. + * @param content Content of the signal. Should be a JSON serializable object or primitive. + * @param targetClientId Optional. When specified, the signal is only sent to the provided client id. + */ + submitSignal: ( + type: string, + content: unknown, + targetClientId?: string + ) => void; +} + +/** + * @hidden + */ +interface ILiveEventInternalEmitterEvents extends IEvent { + /** + * Event listener for error events + * @param event update + * @param listener listener function + * @param listener.error the error instance + */ + (event: "error", listener: (error: any) => void): void; + /** + * Event listener for events emitted through `LiveEventScope` + * @param event update + * @param listener listener function + * @param listener.event the event instance + * @param listener.local whether the event was initiated from the local client + */ + (event: string, listener: (event: any, local: boolean) => void): void; } /** @@ -57,9 +90,11 @@ export interface IRuntimeSignaler { * events. */ export class LiveEventScope extends TypedEventEmitter { - private readonly emitter = new EventEmitter(); + private readonly emitter = + new TypedEventEmitter(); private readonly _runtime: IRuntimeSignaler; private _allowedRoles: UserMeetingRole[]; + private _logger: LiveTelemetryLogger; /** * Only throw role validation failed errors for events that are associated with this scope. @@ -81,6 +116,7 @@ export class LiveEventScope extends TypedEventEmitter { super(); this._runtime = runtime; this._allowedRoles = allowedRoles || []; + this._logger = new LiveTelemetryLogger(runtime, _liveRuntime); this.emitter.on("error", (error) => { this.emit("error", error); }); @@ -91,9 +127,25 @@ export class LiveEventScope extends TypedEventEmitter { // We'll overwrite the contents clientId with the messages clientId which can't be // spoofed. const clientId = message.clientId; - message.content.clientId = clientId; - this.emitToListeners(clientId, message.content, local); + if (isILiveEvent(message.content)) { + const content = message.content; + // While the Fluid odsp-driver currently supports targeted signals, it isn't guaranteed in other drivers. + // As of Fluid v2.2.0, azure-client and tinylicious do not support it currently. + // For consistency, we return early when the local client is not the targeted one. + if (message.targetClientId && content.targetClientId) { + // If we know the true targetClientId, we are in a supported driver so we override it + content.targetClientId = message.targetClientId; + } + if ( + !local && + content.targetClientId && + content.targetClientId !== this._runtime.clientId + ) + return; + content.clientId = clientId; + this.emitToListeners(clientId, content, local); + } }); } @@ -153,6 +205,7 @@ export class LiveEventScope extends TypedEventEmitter { * @template TEvent Type of event to send. * @param eventName Name of the event to send. * @param evt Optional. Partial event object to send. The `ILiveEvent.name`, + * @param targetClientId Optional. When specified, the signal is only sent to the provided client id. * `ILiveEvent.timestamp`, and `ILiveEvent.clientId` * fields will be automatically populated prior to sending. * @returns The full event, including `ILiveEvent.name`, @@ -160,11 +213,17 @@ export class LiveEventScope extends TypedEventEmitter { */ public async sendEvent( eventName: string, - evt: TEvent + evt: TEvent, + targetClientId?: string ): Promise> { - const event = await this.createEvent(eventName, evt); + const event = await this.createEvent(eventName, evt, targetClientId); // Send event - this._runtime.submitSignal(eventName, event); + this._runtime.submitSignal(eventName, event, targetClientId); + // Emit event to local client only when targetClientId is specified and not the local client + // This is due to new versions of fluid not emitting the signal to the local client after sending it to other clients + if (targetClientId && targetClientId !== this._runtime.clientId) { + this.emitToListeners(event.clientId, event, true); + } return event; } @@ -190,7 +249,8 @@ export class LiveEventScope extends TypedEventEmitter { private async createEvent( eventName: string, - evt: TEvent + evt: TEvent, + targetClientId?: string ): Promise> { const clientId = await this.waitUntilConnected(); const isAllowed = await this._liveRuntime.verifyRolesAllowed( @@ -207,6 +267,7 @@ export class LiveEventScope extends TypedEventEmitter { // Clone passed in event and fill out required props. const clone: ILiveEvent = { clientId, + targetClientId, name: eventName, timestamp: this._liveRuntime.getTimestamp(), data: evt, @@ -233,8 +294,13 @@ export class LiveEventScope extends TypedEventEmitter { if (value) { this.emitter.emit(event.name, event, local); } else if (this.throwForEvents.includes(event.name)) { - this._runtime.logger.sendErrorEvent( - { eventName: "LiveEvent:invalidRole" }, + const error = new Error( + `The clientId of "${clientId}" doesn't have a role of ${JSON.stringify( + this._allowedRoles + )}.` + ); + this._logger.sendErrorEvent( + "LiveEvent:invalidRole", new Error( `The clientId of "${clientId}" doesn't have a role of ${JSON.stringify( this._allowedRoles @@ -244,10 +310,7 @@ export class LiveEventScope extends TypedEventEmitter { } }) .catch((err) => { - this._runtime.logger.sendErrorEvent( - { eventName: "LiveEvent:invalidRole" }, - err - ); + this._logger.sendErrorEvent("LiveEvent:invalidRole", err); }); } } diff --git a/packages/live-share/src/LiveEventSource.ts b/packages/live-share/src/internals/LiveEventSource.ts similarity index 78% rename from packages/live-share/src/LiveEventSource.ts rename to packages/live-share/src/internals/LiveEventSource.ts index d81f5933e..20dfdf5d2 100644 --- a/packages/live-share/src/LiveEventSource.ts +++ b/packages/live-share/src/internals/LiveEventSource.ts @@ -3,8 +3,8 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { ILiveEvent } from "./interfaces"; -import { LiveEventScope } from "./LiveEventScope"; +import { ILiveEvent } from "../interfaces.js"; +import { LiveEventScope } from "./LiveEventScope.js"; /** * Broadcasts live share events to all clients and can be received by an `LiveEventTarget`. @@ -15,7 +15,7 @@ import { LiveEventScope } from "./LiveEventScope"; * @template TEvent Type of event to broadcast. */ export class LiveEventSource { - private _scope: LiveEventScope; + protected _scope: LiveEventScope; private _eventName: string; /** @@ -31,13 +31,21 @@ export class LiveEventSource { /** * Broadcasts an event to any listening `LiveEventTarget` instances. * @param evt Optional. Partial event object to send. The `ILiveEvent.name`, + * @param targetClientId Optional. When specified, the signal is only sent to the provided client id. * `ILiveEvent.timestamp`, and `ILiveEvent.clientId` * fields will be automatically populated prior to sending. * @returns The full event, including `ILiveEvent.name`, * `ILiveEvent.timestamp`, and `ILiveEvent.clientId` fields if known. */ - public async sendEvent(evt: TEvent): Promise> { - return await this._scope.sendEvent(this._eventName, evt); + public async sendEvent( + evt: TEvent, + targetClientId?: string + ): Promise> { + return await this._scope.sendEvent( + this._eventName, + evt, + targetClientId + ); } /** diff --git a/packages/live-share/src/LiveEventTarget.ts b/packages/live-share/src/internals/LiveEventTarget.ts similarity index 94% rename from packages/live-share/src/LiveEventTarget.ts rename to packages/live-share/src/internals/LiveEventTarget.ts index 13ad02d4a..e126c38b9 100644 --- a/packages/live-share/src/LiveEventTarget.ts +++ b/packages/live-share/src/internals/LiveEventTarget.ts @@ -3,8 +3,8 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { LiveEventScope, LiveEventListener } from "./LiveEventScope"; -import { LiveEventSource } from "./LiveEventSource"; +import { LiveEventScope, LiveEventListener } from "./LiveEventScope.js"; +import { LiveEventSource } from "./LiveEventSource.js"; /** * Receives events broadcast by an `LiveEventSource`. diff --git a/packages/live-share/src/internals/LiveObjectManager.ts b/packages/live-share/src/internals/LiveObjectManager.ts index b42e75e82..5d771e3ea 100644 --- a/packages/live-share/src/internals/LiveObjectManager.ts +++ b/packages/live-share/src/internals/LiveObjectManager.ts @@ -3,25 +3,23 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { IInboundSignalMessage } from "@fluidframework/runtime-definitions"; -import { TypedEventEmitter } from "@fluidframework/common-utils"; -import { IRuntimeSignaler } from "../LiveEventScope"; -import { LiveShareRuntime } from "../LiveShareRuntime"; -import { IContainerRuntimeSignaler, ILiveEvent } from "../interfaces"; -import { LiveEvent } from "../LiveEvent"; +import { IInboundSignalMessage } from "@fluidframework/runtime-definitions/legacy"; +import { TypedEventEmitter } from "@fluid-internal/client-utils"; +import { IRuntimeSignaler } from "./LiveEventScope.js"; +import { LiveShareRuntime } from "./LiveShareRuntime.js"; +import { IContainerRuntimeSignaler, ILiveEvent } from "../interfaces.js"; +import { IAzureAudience } from "@fluidframework/azure-client"; +import { isILiveEvent } from "./type-guards.js"; +import { ObjectSynchronizerEvents } from "./consts.js"; +import { cloneValue, isNewerEvent, waitUntilConnected } from "./utils.js"; +import { ContainerSynchronizer } from "./ContainerSynchronizer.js"; import { - ContainerSynchronizer, GetAndUpdateStateHandlers, IContainerLiveObjectStoreEvents, ILiveClientEventMap, ILiveObjectStore, - ObjectSynchronizerEvents, StateSyncEventContent, - cloneValue, - isILiveEvent, - waitUntilConnected, -} from "./"; -import { IAzureAudience } from "@fluidframework/azure-client"; +} from "./internal-interfaces.js"; /** * @hidden @@ -254,6 +252,16 @@ export class LiveObjectManager extends TypedEventEmitter { + initialState: TState; + updateState: UpdateSynchronizationState; + getLocalUserCanSend: GetLocalUserCanSend; + shouldUpdateTimestampPeriodically?: boolean | undefined; + enableBackgroundUpdates?: boolean | undefined; +} /** * @internal @@ -55,8 +72,11 @@ import { */ export class LiveObjectSynchronizer { private _isDisposed = false; - private _joinedListener: (clientId: string, timestamp: number) => void = - () => {}; + private _joinedListener: (params: { + objectId: string; + clientId: string; + timestamp: number; + }) => void = () => {}; /** * Creates a new `LiveObjectSynchronizer` instance. @@ -71,6 +91,27 @@ export class LiveObjectSynchronizer { private readonly liveRuntime: LiveShareRuntime ) {} + /** + * Starts a `LiveObjectSynchronizer` instance. + * + * @param {LiveObjectSynchronizerStartParams} params Start params for LiveObjectSynchronizer. + */ + public start({ + initialState, + updateState, + getLocalUserCanSend, + shouldUpdateTimestampPeriodically = false, + enableBackgroundUpdates = true, + }: LiveObjectSynchronizerStartParams): Promise { + return this.startInternal( + initialState, + updateState, + getLocalUserCanSend, + shouldUpdateTimestampPeriodically, + enableBackgroundUpdates + ); + } + /** * Starts a `LiveObjectSynchronizer` instance. * @@ -80,12 +121,12 @@ export class LiveObjectSynchronizer { * @param shouldUpdateTimestampPeriodically flag for updating the timestamp whenever sending out a periodic update. * @param enableBackgroundUpdates flag for enabling/disabling background updates. True by default. */ - public start( + private startInternal( initialState: TState, updateState: UpdateSynchronizationState, getLocalUserCanSend: GetLocalUserCanSend, - shouldUpdateTimestampPeriodically = false, - enableBackgroundUpdates = true + shouldUpdateTimestampPeriodically: boolean, + enableBackgroundUpdates: boolean ): Promise { return this.liveRuntime.objectManager.registerObject( this.id, @@ -154,6 +195,7 @@ export class LiveObjectSynchronizer { /** * Sends a one-time event through the synchronizer * @param data the date for the event to send + * @param targetClientId Optional. When specified, the signal is only sent to the provided client id. * @returns the event that was sent */ public sendEvent(data: TState): Promise> { @@ -183,15 +225,12 @@ export class LiveObjectSynchronizer { callback: (clientId: string, timestamp: number) => void ) { this.liveRuntime.objectManager.off("joined", this._joinedListener); - this._joinedListener = callback; - - this.liveRuntime.objectManager.on( - "joined", - ({ objectId, clientId, timestamp }) => { - if (objectId === this.id) { - this._joinedListener(clientId, timestamp); - } + this._joinedListener = ({ objectId, clientId, timestamp }) => { + if (objectId === this.id) { + callback(clientId, timestamp); } - ); + }; + + this.liveRuntime.objectManager.on("joined", this._joinedListener); } } diff --git a/packages/live-share/src/internals/LiveShareHostDecorator.ts b/packages/live-share/src/internals/LiveShareHostDecorator.ts index 4c642d34f..8c81f2ced 100644 --- a/packages/live-share/src/internals/LiveShareHostDecorator.ts +++ b/packages/live-share/src/internals/LiveShareHostDecorator.ts @@ -3,29 +3,24 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { UserMeetingRole, IClientInfo } from "../interfaces"; -import { BackwardsCompatibilityGetClientInfoRetrySchedule } from "./BackwardsCompatibilityHostDecorator"; -import { BaseHostDecorator } from "./BaseHostDecorator"; -import { RequestCache } from "./RequestCache"; +import { UserMeetingRole, IClientInfo } from "../interfaces.js"; +import { BaseHostDecorator } from "./BaseHostDecorator.js"; +import { RequestCache } from "./RequestCache.js"; import { - isErrorLike, isIClientInfo, isMobileWorkaroundRolesResponse, isClientRolesResponse, -} from "./type-guards"; -import { waitForResult } from "./utils"; +} from "./type-guards.js"; +import { waitForResult } from "./utils.js"; -const EXPONENTIAL_BACKOFF_SCHEDULE = [100, 200, 200, 400, 600]; +const EXPONENTIAL_BACKOFF_SCHEDULE = [200, 200, 400, 800, 1000]; const CACHE_LIFETIME = 4 * 1000; /** * @hidden * Live Share Host decorator used to reduce rapid duplicate requests. */ -export class LiveShareHostDecorator - extends BaseHostDecorator - implements BackwardsCompatibilityGetClientInfoRetrySchedule -{ +export class LiveShareHostDecorator extends BaseHostDecorator { private readonly _registerRequestCache: RequestCache = new RequestCache(CACHE_LIFETIME); private readonly _userInfoRequestCache: RequestCache< @@ -63,26 +58,7 @@ export class LiveShareHostDecorator } return null; }, - (error: unknown) => { - return new Error( - `LiveShareHostDecorator: getting client info for a remote client ID for reason: ${ - isErrorLike(error) ? error.message : "unknown" - }` - ); - }, - retrySchedule ?? EXPONENTIAL_BACKOFF_SCHEDULE, - (error: unknown) => { - // Errors here do not include any timeout errors, so if it is an error from "fakeId", we immediately reject it - if (clientId === "fakeId") { - return new Error( - isErrorLike(error) - ? error.message - : "an unknown error occurred" - ); - } - return null; - }, - lateFinish // TODO: delete (not a breaking change to remove, see InternalDontUseGetClientInfoRetryPolyfill) + retrySchedule ?? EXPONENTIAL_BACKOFF_SCHEDULE ); }); } @@ -107,13 +83,6 @@ export class LiveShareHostDecorator } return null; }, - (reason: unknown) => { - return new Error( - `LiveShareHostDecorator: registering local client ID for reason: ${ - isErrorLike(reason) ? reason.message : "unknown" - }` - ); - }, EXPONENTIAL_BACKOFF_SCHEDULE ); }); diff --git a/packages/live-share/src/LiveShareRuntime.ts b/packages/live-share/src/internals/LiveShareRuntime.ts similarity index 89% rename from packages/live-share/src/LiveShareRuntime.ts rename to packages/live-share/src/internals/LiveShareRuntime.ts index a6d622fba..504934415 100644 --- a/packages/live-share/src/LiveShareRuntime.ts +++ b/packages/live-share/src/internals/LiveShareRuntime.ts @@ -1,5 +1,4 @@ -import { assert } from "@fluidframework/common-utils"; -import { HostTimestampProvider } from "./HostTimestampProvider"; +import { HostTimestampProvider } from "../HostTimestampProvider.js"; import { IClientInfo, ILiveShareHost, @@ -7,17 +6,14 @@ import { ITimestampProvider, UserMeetingRole, IContainerRuntimeSignaler, -} from "./interfaces"; -import { - BackwardsCompatibilityHostDecorator, - LiveShareHostDecorator, - RoleVerifier, - isTimestampProvider, - LiveObjectManager, - FormatFixHostDecorator, -} from "./internals"; +} from "../interfaces.js"; import { IAzureAudience } from "@fluidframework/azure-client"; -import { ILiveShareClientOptions } from "./LiveShareClient"; +import { ILiveShareClientOptions } from "../LiveShareClient.js"; +import { isTimestampProvider } from "./type-guards.js"; +import { LiveObjectManager } from "./LiveObjectManager.js"; +import { RoleVerifier } from "./RoleVerifier.js"; +import { LiveShareHostDecorator } from "./LiveShareHostDecorator.js"; +import { UnexpectedError } from "../errors.js"; /** * Runtime for LiveDataObject, which is used to do things like validate roles, get a timestamp @@ -44,13 +40,8 @@ export class LiveShareRuntime { options?: ILiveShareClientOptions, decorate: boolean = true ) { - // BackwardsCompatibilityHostDecorator is used for backwards compatibility with older versions of the Teams client. // LiveShareHostDecorator is used as a thin caching layer for some host APIs. - this._host = decorate - ? new BackwardsCompatibilityHostDecorator( - new LiveShareHostDecorator(new FormatFixHostDecorator(host)) - ) - : host; + this._host = decorate ? new LiveShareHostDecorator(host) : host; this._timestampProvider = options?.timestampProvider ?? new HostTimestampProvider(this._host); this._roleVerifier = @@ -63,8 +54,9 @@ export class LiveShareRuntime { * `LiveObjectSynchronizerManager` instance */ public get objectManager(): LiveObjectManager { - assert( + UnexpectedError.assert( this._objectManager !== null, + "LiveShareRuntime:objectManager", "LiveObjectSynchronizerManager not initialized." ); return this._objectManager; @@ -84,6 +76,13 @@ export class LiveShareRuntime { return this._host; } + /** + * `IAzureAudience` instance + */ + public get audience(): IAzureAudience | undefined { + return this._audience; + } + /** * Setting for whether `LiveDataObject` instances using `LiveObjectSynchronizer` can send background updates. * Default value is `true`. @@ -157,13 +156,8 @@ export class LiveShareRuntime { * @param decorate choose whether or not to automatically decorate host with `BackwardsCompatibilityHostDecorator` and `LiveShareHostDecorator` */ public setHost(host: ILiveShareHost, decorate: boolean = true) { - // BackwardsCompatibilityHostDecorator is used for backwards compatibility with older versions of the Teams client. // LiveShareHostDecorator is used as a thin caching layer for some host APIs. - this._host = decorate - ? new BackwardsCompatibilityHostDecorator( - new LiveShareHostDecorator(host) - ) - : host; + this._host = decorate ? new LiveShareHostDecorator(host) : host; if (this._timestampProvider instanceof HostTimestampProvider) { this._timestampProvider.stop(); this.setTimestampProvider(new HostTimestampProvider(this._host)); diff --git a/packages/live-share/src/internals/LiveShareTokenProvider.ts b/packages/live-share/src/internals/LiveShareTokenProvider.ts index f6418934b..a30b4bb69 100644 --- a/packages/live-share/src/internals/LiveShareTokenProvider.ts +++ b/packages/live-share/src/internals/LiveShareTokenProvider.ts @@ -7,7 +7,7 @@ import { ITokenProvider, ITokenResponse, } from "@fluidframework/routerlicious-driver"; -import { ILiveShareHost } from "../interfaces"; +import { ILiveShareHost } from "../interfaces.js"; /** * @hidden diff --git a/packages/live-share/src/internals/RoleVerifier.ts b/packages/live-share/src/internals/RoleVerifier.ts index 590894ba7..fcaa2391e 100644 --- a/packages/live-share/src/internals/RoleVerifier.ts +++ b/packages/live-share/src/internals/RoleVerifier.ts @@ -3,7 +3,11 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { ILiveShareHost, IRoleVerifier, UserMeetingRole } from "../interfaces"; +import { + ILiveShareHost, + IRoleVerifier, + UserMeetingRole, +} from "../interfaces.js"; /** * @hidden */ diff --git a/packages/live-share/src/internals/ThrottledEventQueue.ts b/packages/live-share/src/internals/ThrottledEventQueue.ts index 145c90ce9..dffe0745c 100644 --- a/packages/live-share/src/internals/ThrottledEventQueue.ts +++ b/packages/live-share/src/internals/ThrottledEventQueue.ts @@ -1,9 +1,9 @@ -import { ILiveEvent } from "../interfaces"; -import { ContainerSynchronizer } from "./ContainerSynchronizer"; -import { Deferred } from "./Deferred"; -import { ObjectSynchronizerEvents } from "./consts"; -import { UnexpectedError } from "../errors"; -import { StateSyncEventContent } from "./internal-interfaces"; +import { ILiveEvent } from "../interfaces.js"; +import { ContainerSynchronizer } from "./ContainerSynchronizer.js"; +import { Deferred } from "./Deferred.js"; +import { ObjectSynchronizerEvents } from "./consts.js"; +import { UnexpectedError } from "../errors.js"; +import { StateSyncEventContent } from "./internal-interfaces.js"; /** * @hidden @@ -17,7 +17,7 @@ export class ThrottledEventQueue { private _events: StateSyncEventContent = {}; private _throttleIntervalMilli: number; private _deferred: Deferred> | undefined; - private _hTimer: NodeJS.Timeout | undefined; + private _hTimer?: any; /** * @hidden * Queue for grouping multiple signal events together. diff --git a/packages/live-share/src/internals/consts.ts b/packages/live-share/src/internals/consts.ts index d09d0441a..50d404e81 100644 --- a/packages/live-share/src/internals/consts.ts +++ b/packages/live-share/src/internals/consts.ts @@ -3,6 +3,8 @@ * Licensed under the Microsoft Live Share SDK License. */ +import { CompatibilityMode } from "@fluidframework/azure-client"; + /** * List of telemetry events. * @hidden @@ -41,3 +43,8 @@ export const ObjectSynchronizerEvents = { * @hidden */ export const LiveShareReportIssueLink = "https://aka.ms/teamsliveshare/issue"; + +/** + * @hidden + */ +export const FluidCompatibilityMode: CompatibilityMode = "2"; diff --git a/packages/live-share/src/internals/fluid-duplicated.ts b/packages/live-share/src/internals/fluid-duplicated.ts new file mode 100644 index 000000000..108d29e70 --- /dev/null +++ b/packages/live-share/src/internals/fluid-duplicated.ts @@ -0,0 +1,105 @@ +import { type IFluidDataStoreFactory } from "@fluidframework/runtime-definitions/legacy"; +import { type IChannelFactory } from "@fluidframework/datastore-definitions/legacy"; +import { IFluidLoadable } from "@fluidframework/core-interfaces"; +import type { SharedObjectKind } from "@fluidframework/shared-object-base"; +/** + * COPIED FROM @fluidframework/fluid-static + * + * A mapping of string identifiers to classes that will later be used to instantiate a corresponding `DataObject` + * or `SharedObject`. + */ +export type LoadableObjectClassRecord = Record; + +/** + * COPIED FROM @fluidframework/fluid-static + * + * A class that has a factory that can create a `DataObject` and a + * constructor that will return the type of the `DataObject`. + * + * @typeParam T - The class of the `DataObject`. + * @privateRemarks + * Having both `factory` and constructor is redundant. + * TODO: It appears the factory is what's used, so the constructor should be removed once factory provides strong typing. + */ +export interface DataObjectClass { + readonly factory: IFluidDataStoreFactory; + new (...args: any[]): T; +} + +/** + * COPIED FROM @fluidframework/fluid-static + * + * An internal type used by the internal type guard isDataObjectClass to cast a + * DataObjectClass to a type that is strongly coupled to IFluidDataStoreFactory. + * Unlike the external and exported type DataObjectClass which is + * weakly coupled to the IFluidDataStoreFactory to prevent leaking internals. + */ +type InternalDataObjectClass = DataObjectClass & + Record<"factory", IFluidDataStoreFactory>; + +/** + * COPIED FROM @fluidframework/fluid-static + * + * Runtime check to determine if a class is a DataObject type + */ +const isDataObjectClass = ( + obj: unknown +): obj is InternalDataObjectClass => { + const maybe = obj as + | Partial> + | undefined; + return ( + maybe?.factory?.IFluidDataStoreFactory !== undefined && + maybe?.factory?.IFluidDataStoreFactory === maybe?.factory + ); +}; + +/** + * COPIED FROM @fluidframework/fluid-static + * + * Runtime check to determine if a class is a SharedObject type + */ +const isSharedObjectClass = ( + obj: unknown +): obj is SharedObjectClass => { + const maybe = obj as Partial> | undefined; + return maybe?.getFactory !== undefined; +}; + +/** + * COPIED FROM @fluidframework/fluid-static + * + * A class that has a factory that can create a DDSes (`SharedObject`s) and a + * constructor that will return the type of the `DataObject`. + * + * @typeParam T - The class of the `SharedObject`. + * @public + */ +type SharedObjectClass = { + readonly getFactory: () => IChannelFactory; +} & LoadableObjectCtor; + +/** + * COPIED FROM @fluidframework/fluid-static + * + * An object with a constructor that will return an {@link @fluidframework/core-interfaces#IFluidLoadable}. + * + * @typeParam T - The class of the loadable object. + * @public + */ +export type LoadableObjectCtor = new ( + ...args: any[] +) => T; + +/** + * Combining above to get factory type string. + */ +export const getFactoryName = (obj: unknown): string | undefined => { + if (isDataObjectClass(obj)) { + return obj.factory.type; + } else if (isSharedObjectClass(obj)) { + return obj.getFactory().type; + } else { + return undefined; + } +}; diff --git a/packages/live-share/src/internals/index.ts b/packages/live-share/src/internals/index.ts deleted file mode 100644 index 6892862e5..000000000 --- a/packages/live-share/src/internals/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -/*! - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Microsoft Live Share SDK License. - */ - -export * from "./consts"; -export * from "./LiveShareTokenProvider"; -export * from "./RequestCache"; -export * from "./RoleVerifier"; -export * from "./utils"; -export * from "./LiveShareHostDecorator"; -export * from "./BackwardsCompatibilityHostDecorator"; -export * from "./Deferred"; -export * from "./type-guards"; -export * from "./internal-interfaces"; -export * from "./LiveObjectManager"; -export * from "./ContainerSynchronizer"; -export * from "./FormatFixHostDecorator"; diff --git a/packages/live-share/src/internals/internal-interfaces.ts b/packages/live-share/src/internals/internal-interfaces.ts index 6155b087d..ca9a448e8 100644 --- a/packages/live-share/src/internals/internal-interfaces.ts +++ b/packages/live-share/src/internals/internal-interfaces.ts @@ -2,8 +2,8 @@ import { GetLocalUserCanSend, ILiveEvent, UpdateSynchronizationState, -} from "../interfaces"; -import { IEvent } from "@fluidframework/common-definitions"; +} from "../interfaces.js"; +import { IEvent } from "@fluidframework/core-interfaces"; /** * @hidden diff --git a/packages/live-share/src/test/MockContainerRuntimeSignaler.ts b/packages/live-share/src/internals/mock/MockContainerRuntimeSignaler.ts similarity index 96% rename from packages/live-share/src/test/MockContainerRuntimeSignaler.ts rename to packages/live-share/src/internals/mock/MockContainerRuntimeSignaler.ts index aa47433de..fd6bb887b 100644 --- a/packages/live-share/src/test/MockContainerRuntimeSignaler.ts +++ b/packages/live-share/src/internals/mock/MockContainerRuntimeSignaler.ts @@ -3,8 +3,8 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { IInboundSignalMessage } from "@fluidframework/runtime-definitions"; -import { IContainerRuntimeSignaler } from "../interfaces"; +import { IInboundSignalMessage } from "@fluidframework/runtime-definitions/legacy"; +import { IContainerRuntimeSignaler } from "../../interfaces.js"; import { v4 } from "uuid"; export class MockContainerRuntimeSignaler implements IContainerRuntimeSignaler { diff --git a/packages/live-share/src/test/MockLiveShareRuntime.ts b/packages/live-share/src/internals/mock/MockLiveShareRuntime.ts similarity index 54% rename from packages/live-share/src/test/MockLiveShareRuntime.ts rename to packages/live-share/src/internals/mock/MockLiveShareRuntime.ts index 3c04469b1..6c3317eae 100644 --- a/packages/live-share/src/test/MockLiveShareRuntime.ts +++ b/packages/live-share/src/internals/mock/MockLiveShareRuntime.ts @@ -1,14 +1,34 @@ -import { LiveShareRuntime } from "../LiveShareRuntime"; -import { TestLiveShareHost } from "../TestLiveShareHost"; -import { IContainerRuntimeSignaler, ITimestampProvider } from "../interfaces"; -import { MockContainerRuntimeSignaler } from "./MockContainerRuntimeSignaler"; -import { LocalTimestampProvider } from "../LocalTimestampProvider"; +import { LiveShareRuntime } from "../LiveShareRuntime.js"; +import { TestLiveShareHost } from "../../TestLiveShareHost.js"; +import { + IContainerRuntimeSignaler, + ITimestampProvider, +} from "../../interfaces.js"; +import { MockContainerRuntimeSignaler } from "./MockContainerRuntimeSignaler.js"; +import { LocalTimestampProvider } from "../../LocalTimestampProvider.js"; +import { ITokenProvider, ITokenResponse } from "@fluidframework/azure-client"; +export class MockTokenProvider implements ITokenProvider { + public async fetchOrdererToken( + _tenantId: string, + _documentId?: string, + _refresh?: boolean + ): Promise { + return Promise.reject(); + } + public async fetchStorageToken( + _tenantId: string, + _documentId?: string, + _refresh?: boolean + ): Promise { + return Promise.reject(); + } +} export class MockLiveShareRuntime extends LiveShareRuntime { constructor( shouldCreateMockContainer = false, private readonly updateInterval = 10000, - host = TestLiveShareHost.create(), + host = TestLiveShareHost.create(new MockTokenProvider()), timestampProvider: ITimestampProvider = new LocalTimestampProvider() ) { super(host, { @@ -34,10 +54,12 @@ export class MockLiveShareRuntime extends LiveShareRuntime { return this._containerRuntime; return undefined; } - connectToOtherRuntime(otherLiveRuntime: MockLiveShareRuntime) { + connectToOtherRuntime(...otherLiveRuntimes: MockLiveShareRuntime[]) { MockContainerRuntimeSignaler.connectContainers([ this.getLocalMockContainer()!, - otherLiveRuntime.getLocalMockContainer()!, + ...otherLiveRuntimes.map( + (runtime) => runtime.getLocalMockContainer()! + ), ]); } } diff --git a/packages/live-share/src/test/MockRoleVerifier.ts b/packages/live-share/src/internals/mock/MockRoleVerifier.ts similarity index 89% rename from packages/live-share/src/test/MockRoleVerifier.ts rename to packages/live-share/src/internals/mock/MockRoleVerifier.ts index 6b81e7d2a..e8f06211b 100644 --- a/packages/live-share/src/test/MockRoleVerifier.ts +++ b/packages/live-share/src/internals/mock/MockRoleVerifier.ts @@ -3,7 +3,7 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { IRoleVerifier, UserMeetingRole } from "../interfaces"; +import { IRoleVerifier, UserMeetingRole } from "../../interfaces.js"; export class MockRoleVerifier implements IRoleVerifier { private _sendersRoles: UserMeetingRole[]; @@ -14,7 +14,7 @@ export class MockRoleVerifier implements IRoleVerifier { public blocked = false; public called = false; - public clientId: string; + public clientId: string = ""; public verifyRolesAllowed( clientId: string, diff --git a/packages/live-share/src/test/MockRuntimeSignaler.ts b/packages/live-share/src/internals/mock/MockRuntimeSignaler.ts similarity index 92% rename from packages/live-share/src/test/MockRuntimeSignaler.ts rename to packages/live-share/src/internals/mock/MockRuntimeSignaler.ts index 10ab7514e..acb69e1f0 100644 --- a/packages/live-share/src/test/MockRuntimeSignaler.ts +++ b/packages/live-share/src/internals/mock/MockRuntimeSignaler.ts @@ -3,11 +3,11 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { ITelemetryLogger } from "@fluidframework/common-definitions"; -import { IInboundSignalMessage } from "@fluidframework/runtime-definitions"; -import { MockLogger } from "@fluidframework/telemetry-utils"; -import { IRuntimeSignaler } from "../LiveEventScope"; +import { IInboundSignalMessage } from "@fluidframework/runtime-definitions/legacy"; +import { MockLogger } from "@fluidframework/telemetry-utils/internal"; +import { IRuntimeSignaler } from "../LiveEventScope.js"; import { v4 } from "uuid"; +import { ITelemetryBaseLogger } from "@fluidframework/azure-client"; export class MockRuntimeSignaler implements IRuntimeSignaler { private _connected: MockRuntimeSignaler[] = []; @@ -25,7 +25,7 @@ export class MockRuntimeSignaler implements IRuntimeSignaler { public clientId: string | undefined; public connected: boolean; - public logger: ITelemetryLogger; + public logger: ITelemetryBaseLogger; public connect(): void { if (!this.connected) { diff --git a/packages/live-share/src/test/MockTimestampProvider.ts b/packages/live-share/src/internals/mock/MockTimestampProvider.ts similarity index 88% rename from packages/live-share/src/test/MockTimestampProvider.ts rename to packages/live-share/src/internals/mock/MockTimestampProvider.ts index 565d9b042..16f3f6ea5 100644 --- a/packages/live-share/src/test/MockTimestampProvider.ts +++ b/packages/live-share/src/internals/mock/MockTimestampProvider.ts @@ -3,7 +3,7 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { ITimestampProvider } from "../interfaces"; +import { ITimestampProvider } from "../../interfaces.js"; export class MockTimestampProvider implements ITimestampProvider { public called = false; diff --git a/packages/live-share/src/schema-injection-utils.ts b/packages/live-share/src/internals/schema-injection-utils.ts similarity index 74% rename from packages/live-share/src/schema-injection-utils.ts rename to packages/live-share/src/internals/schema-injection-utils.ts index f96764859..90fb05703 100644 --- a/packages/live-share/src/schema-injection-utils.ts +++ b/packages/live-share/src/internals/schema-injection-utils.ts @@ -1,16 +1,16 @@ -import { DataObjectTypes, IDataObjectProps } from "@fluidframework/aqueduct"; +import { + DataObjectTypes, + IDataObjectProps, +} from "@fluidframework/aqueduct/legacy"; import { IFluidLoadable } from "@fluidframework/core-interfaces"; +import { LiveDataObject } from "./LiveDataObject.js"; +import { LiveShareRuntime } from "./LiveShareRuntime.js"; import { LoadableObjectCtor, - DataObjectClass, -} from "@fluidframework/fluid-static"; -import { LiveDataObject } from "./LiveDataObject"; -import { LiveShareRuntime } from "./LiveShareRuntime"; -import { - ContainerSchema, - LoadableObjectClass, LoadableObjectClassRecord, -} from "fluid-framework"; + DataObjectClass, +} from "./fluid-duplicated.js"; +import { ContainerSchema, SharedObjectKind } from "fluid-framework"; /** * A LiveObjectClass is a class that has a factory that can create a DDS (SharedObject) and a @@ -34,20 +34,19 @@ type LiveObjectClass = { * @param liveRuntime LiveShareRuntime instance * @returns ContainerSchema with injected dependencies */ -export function getLiveContainerSchema( - schema: ContainerSchema, - liveRuntime: LiveShareRuntime -): ContainerSchema { +export function getLiveContainerSchema< + const TContainerSchema extends ContainerSchema, +>(schema: TContainerSchema, liveRuntime: LiveShareRuntime): TContainerSchema { // Each container must proxy LiveDataObject classes separately. // This map is used to de-duplicate proxies for each class. - const injectedClasses = new Map>(); + const injectedClasses = new Map>(); const initialObjectEntries = Object.entries(schema.initialObjects).map( - ([key, ObjectClass]) => { + ([key, objectClass]) => { return [ key, - getLiveDataObjectClass( - ObjectClass, + getLiveDataObjectKind( + objectClass, liveRuntime, injectedClasses ), @@ -59,21 +58,10 @@ export function getLiveContainerSchema( return { initialObjects: newInitialObjects, - dynamicObjectTypes: schema.dynamicObjectTypes?.map((ObjectClass) => - getLiveDataObjectClass(ObjectClass, liveRuntime, injectedClasses) + dynamicObjectTypes: schema.dynamicObjectTypes?.map((objectClass) => + getLiveDataObjectKind(objectClass, liveRuntime, injectedClasses) ), - }; -} - -/** - * @deprecated - * Use {@link getLiveContainerSchema} instead. - */ -export function getLiveContainerSchemaProxy( - schema: ContainerSchema, - liveRuntime: LiveShareRuntime -): ContainerSchema { - return getLiveContainerSchema(schema, liveRuntime); + } as TContainerSchema; } /** @@ -83,35 +71,35 @@ export function getLiveContainerSchemaProxy( * @remarks * Can be used to follow the pattern of this package's unit tests for custom `LiveDataObject` implementations. * - * @param ObjectClass a `LoadableObjectClass` instance to inject with the `liveRuntime` provided, if needed. + * @param ObjectKind a `SharedObjectKind` instance to inject with the `liveRuntime` provided, if needed. * @param liveRuntime the `LiveShareRuntime` instance to inject into provided `LiveDataObject` instances. * @param injectedClasses Optional. Map of classes that have already been injected. Default value is an empty map. - * @returns the new `LoadableObjectClass` if injected, or the same `ObjectClass` passed in if not. + * @returns the new `SharedObjectKind` if injected, or the same `ObjectKind` passed in if not. */ -export function getLiveDataObjectClass( - ObjectClass: LoadableObjectClass, +export function getLiveDataObjectKind( + objectClass: SharedObjectKind, liveRuntime: LiveShareRuntime, - injectedClasses: Map> = new Map() -): LoadableObjectClass { - if (isLiveDataObject(ObjectClass)) { + injectedClasses: Map> = new Map() +): SharedObjectKind { + if (isLiveDataObject(objectClass)) { // We should only be proxying one Live Share DDS per type. // This is because Fluid attempts to de-duplicate by comparing classes, but we are dynamically creating proxies. // They then enforce this de-duplication using the factory type name, throwing an error in `parseDataObjectsFromSharedObjects`. // So, we ensure that we only create the proxy once per container. - const typeName = (ObjectClass as any).TypeName; + const typeName = (objectClass as any).TypeName; const CheckExisting = injectedClasses.get(typeName); if (CheckExisting !== undefined) { return CheckExisting; } // Create a new proxy for this type and insert it into proxiedClasses const NewProxy = getLiveDataObjectProxyClassInternal( - ObjectClass, + objectClass, liveRuntime - ); + ) as unknown as SharedObjectKind; injectedClasses.set(typeName, NewProxy); return NewProxy; } - return ObjectClass; + return objectClass; } /** @@ -126,7 +114,7 @@ function isLiveDataObject(value: any): value is typeof LiveDataObject { * Create a new class extending LiveDataObject to inject in _liveRuntime */ function getLiveDataObjectProxyClassInternal< - I extends DataObjectTypes = DataObjectTypes + I extends DataObjectTypes = DataObjectTypes, >( BaseClass: typeof LiveDataObject, runtime: LiveShareRuntime @@ -161,13 +149,15 @@ function getLiveDataObjectProxyClassInternal< public static TypeName = (BaseClass as any).TypeName; public static readonly factory = new Proxy((BaseClass as any).factory, { get: function (target, prop, receiver) { - if (prop === "ctor") { - return ProxiedBaseClass; + if (prop === "createProps") { + return { + ...Reflect.get(target, prop, receiver), + ctor: ProxiedBaseClass, + }; } return Reflect.get(target, prop, receiver); }, }); }; - return DynamicClass; } diff --git a/packages/live-share/src/internals/smuggle.ts b/packages/live-share/src/internals/smuggle.ts new file mode 100644 index 000000000..10a7dc1fd --- /dev/null +++ b/packages/live-share/src/internals/smuggle.ts @@ -0,0 +1,54 @@ +import { DataObject } from "@fluidframework/aqueduct/legacy"; +import { type ISharedDirectory } from "@fluidframework/map/legacy"; +import { type IFluidDataStoreRuntime } from "@fluidframework/datastore-definitions/legacy"; +import { IFluidContainer } from "@fluidframework/fluid-static"; + +/** + * @hidden + */ +export const TurboDirectory = "TURBO_DIRECTORY"; + +/** + * @hidden + */ +export const TurboStateMap = "TURBO_STATE_MAP"; + +/** + * @hidden + */ +export const TurboDynamicObjects = "TURBO_DYNAMIC_OBJECTS"; + +/** + * @hidden + */ +export function getRootDataObject(container: IFluidContainer): DataObject { + interface RootDataObjectSmuggler { + rootDataObject: DataObject; + } + const blah = container as unknown as RootDataObjectSmuggler; + return blah.rootDataObject; +} + +/** + * @hidden + */ +export function getRootDirectory(rootDataObject: DataObject): ISharedDirectory { + interface RootDataObjectDirectorymuggler { + root: ISharedDirectory; + } + const blah = rootDataObject as unknown as RootDataObjectDirectorymuggler; + return blah.root; +} + +/** + * @hidden + */ +export function getContainerRuntime( + rootDataObject: DataObject +): IFluidDataStoreRuntime { + interface RootDataObjectRuntimeSmuggler { + runtime: IFluidDataStoreRuntime; + } + const blah = rootDataObject as unknown as RootDataObjectRuntimeSmuggler; + return blah.runtime; +} diff --git a/packages/live-share/src/internals/test/FormatFixHostDecorator.spec.ts b/packages/live-share/src/internals/test/FormatFixHostDecorator.spec.ts deleted file mode 100644 index bcdf41998..000000000 --- a/packages/live-share/src/internals/test/FormatFixHostDecorator.spec.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { ILiveShareHost, UserMeetingRole, IClientInfo } from "../../interfaces"; -import { strict as assert } from "assert"; -import { FormatFixHostDecorator } from ".."; - -class HostWithAndroidBug { - constructor(private result: unknown) {} - public async getClientInfo( - clientId: string - ): Promise { - return this.result as IClientInfo; - } -} - -describe("FormatFixHostDecorator tests", function () { - it("should map android bug format to expected format 1", async () => { - const hostResponse = { - lock: "972ea631-abc8-4056-ae0e-f4dc7427c4ef", - _loadStates: [UserMeetingRole.organizer], - internalState: "displayName", - }; - const host = new HostWithAndroidBug( - hostResponse - ) as unknown as ILiveShareHost; - const hostWithMapper = new FormatFixHostDecorator(host); - const expectedResult = { - userId: "972ea631-abc8-4056-ae0e-f4dc7427c4ef", - roles: [UserMeetingRole.organizer], - displayName: "displayName", - }; - const result = await hostWithMapper.getClientInfo("test"); - assert( - JSON.stringify(result) === JSON.stringify(expectedResult), - `unexpected result: ${JSON.stringify(result)}` - ); - }); - - it("should map android bug format to expected format 2", async () => { - const hostResponse = { - sup: "FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF", - blah: [UserMeetingRole.organizer], - }; - const host = new HostWithAndroidBug( - hostResponse - ) as unknown as ILiveShareHost; - const hostWithMapper = new FormatFixHostDecorator(host); - const expectedResult = { - userId: "FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF", - roles: [UserMeetingRole.organizer], - displayName: undefined, - }; - const result = await hostWithMapper.getClientInfo("test"); - assert( - JSON.stringify(result) === JSON.stringify(expectedResult), - `unexpected result: ${JSON.stringify(result)}` - ); - }); - - it("should not map if already expected format", async () => { - const hostResponse = { - userId: "userId", - roles: [UserMeetingRole.organizer], - displayName: "displayName", - }; - const host = new HostWithAndroidBug( - hostResponse - ) as unknown as ILiveShareHost; - const hostWithMapper = new FormatFixHostDecorator(host); - const result = await hostWithMapper.getClientInfo("test"); - assert( - JSON.stringify(result) === JSON.stringify(hostResponse), - `unexpected result: ${JSON.stringify(result)}` - ); - }); -}); diff --git a/packages/live-share/src/test/LiveEventScope.spec.ts b/packages/live-share/src/internals/test/LiveEventScope.spec.ts similarity index 85% rename from packages/live-share/src/test/LiveEventScope.spec.ts rename to packages/live-share/src/internals/test/LiveEventScope.spec.ts index 81f7080f6..155ece8a3 100644 --- a/packages/live-share/src/test/LiveEventScope.spec.ts +++ b/packages/live-share/src/internals/test/LiveEventScope.spec.ts @@ -4,14 +4,15 @@ */ import { strict as assert } from "assert"; -import { LiveEventScope } from "../LiveEventScope"; -import { UserMeetingRole } from "../interfaces"; -import { MockRuntimeSignaler } from "./MockRuntimeSignaler"; -import { MockRoleVerifier } from "./MockRoleVerifier"; -import { MockTimestampProvider } from "./MockTimestampProvider"; -import { LocalTimestampProvider } from "../LocalTimestampProvider"; -import { TestLiveShareHost } from "../TestLiveShareHost"; -import { LiveShareRuntime } from "../LiveShareRuntime"; +import { LiveEventScope } from "../LiveEventScope.js"; +import { ILiveEvent, UserMeetingRole } from "../../interfaces.js"; +import { MockRuntimeSignaler } from "../mock/MockRuntimeSignaler.js"; +import { MockRoleVerifier } from "../mock/MockRoleVerifier.js"; +import { MockTimestampProvider } from "../mock/MockTimestampProvider.js"; +import { LocalTimestampProvider } from "../../LocalTimestampProvider.js"; +import { TestLiveShareHost } from "../../TestLiveShareHost.js"; +import { LiveShareRuntime } from "../LiveShareRuntime.js"; +import { MockTokenProvider } from "../mock/MockLiveShareRuntime.js"; function createConnectedSignalers() { const localRuntime = new MockRuntimeSignaler(); @@ -21,21 +22,33 @@ function createConnectedSignalers() { } describe("LiveEventScope", () => { - let localLiveRuntime = new LiveShareRuntime(TestLiveShareHost.create(), { - timestampProvider: new LocalTimestampProvider(), - }); - let remoteLiveRuntime = new LiveShareRuntime(TestLiveShareHost.create(), { - timestampProvider: new LocalTimestampProvider(), - }); + let localLiveRuntime = new LiveShareRuntime( + TestLiveShareHost.create(new MockTokenProvider()), + { + timestampProvider: new LocalTimestampProvider(), + } + ); + let remoteLiveRuntime = new LiveShareRuntime( + TestLiveShareHost.create(new MockTokenProvider()), + { + timestampProvider: new LocalTimestampProvider(), + } + ); afterEach(async () => { // restore defaults - localLiveRuntime = new LiveShareRuntime(TestLiveShareHost.create(), { - timestampProvider: new LocalTimestampProvider(), - }); - remoteLiveRuntime = new LiveShareRuntime(TestLiveShareHost.create(), { - timestampProvider: new LocalTimestampProvider(), - }); + localLiveRuntime = new LiveShareRuntime( + TestLiveShareHost.create(new MockTokenProvider()), + { + timestampProvider: new LocalTimestampProvider(), + } + ); + remoteLiveRuntime = new LiveShareRuntime( + TestLiveShareHost.create(new MockTokenProvider()), + { + timestampProvider: new LocalTimestampProvider(), + } + ); }); it("Should raise local and remote events", async () => { @@ -82,7 +95,8 @@ describe("LiveEventScope", () => { signalers.localRuntime, localLiveRuntime ); - const handler = (evt, local) => triggered++; + const handler = (evt: ILiveEvent, local: boolean) => + triggered++; localScope.onEvent("test", handler); const remoteScope = new LiveEventScope( @@ -151,7 +165,7 @@ describe("LiveEventScope", () => { try { await localScope.sendEvent("test", {}); assert(false, "Event should not have been sent"); - } catch (err) { + } catch (err: any) { assert( err?.message.includes( `The local user doesn't have a role of ["Organizer"]` diff --git a/packages/live-share/src/test/LiveEventSource.spec.ts b/packages/live-share/src/internals/test/LiveEventSource.spec.ts similarity index 55% rename from packages/live-share/src/test/LiveEventSource.spec.ts rename to packages/live-share/src/internals/test/LiveEventSource.spec.ts index 6b85a979a..4cf8ee34e 100644 --- a/packages/live-share/src/test/LiveEventSource.spec.ts +++ b/packages/live-share/src/internals/test/LiveEventSource.spec.ts @@ -4,12 +4,13 @@ */ import { strict as assert } from "assert"; -import { LiveEventScope } from "../LiveEventScope"; -import { LiveEventSource } from "../LiveEventSource"; -import { MockRuntimeSignaler } from "./MockRuntimeSignaler"; -import { LiveShareRuntime } from "../LiveShareRuntime"; -import { TestLiveShareHost } from "../TestLiveShareHost"; -import { LocalTimestampProvider } from "../LocalTimestampProvider"; +import { LiveEventScope } from "../LiveEventScope.js"; +import { LiveEventSource } from "../LiveEventSource.js"; +import { MockRuntimeSignaler } from "../mock/MockRuntimeSignaler.js"; +import { LiveShareRuntime } from "../LiveShareRuntime.js"; +import { TestLiveShareHost } from "../../TestLiveShareHost.js"; +import { LocalTimestampProvider } from "../../LocalTimestampProvider.js"; +import { MockTokenProvider } from "../mock/MockLiveShareRuntime.js"; function createConnectedSignalers() { const localRuntime = new MockRuntimeSignaler(); @@ -19,21 +20,33 @@ function createConnectedSignalers() { } describe("LiveEventSource", () => { - let localLiveRuntime = new LiveShareRuntime(TestLiveShareHost.create(), { - timestampProvider: new LocalTimestampProvider(), - }); - let remoteLiveRuntime = new LiveShareRuntime(TestLiveShareHost.create(), { - timestampProvider: new LocalTimestampProvider(), - }); + let localLiveRuntime = new LiveShareRuntime( + TestLiveShareHost.create(new MockTokenProvider()), + { + timestampProvider: new LocalTimestampProvider(), + } + ); + let remoteLiveRuntime = new LiveShareRuntime( + TestLiveShareHost.create(new MockTokenProvider()), + { + timestampProvider: new LocalTimestampProvider(), + } + ); afterEach(async () => { // restore defaults - localLiveRuntime = new LiveShareRuntime(TestLiveShareHost.create(), { - timestampProvider: new LocalTimestampProvider(), - }); - remoteLiveRuntime = new LiveShareRuntime(TestLiveShareHost.create(), { - timestampProvider: new LocalTimestampProvider(), - }); + localLiveRuntime = new LiveShareRuntime( + TestLiveShareHost.create(new MockTokenProvider()), + { + timestampProvider: new LocalTimestampProvider(), + } + ); + remoteLiveRuntime = new LiveShareRuntime( + TestLiveShareHost.create(new MockTokenProvider()), + { + timestampProvider: new LocalTimestampProvider(), + } + ); }); it("Should send events", (done) => { diff --git a/packages/live-share/src/test/LiveEventTarget.spec.ts b/packages/live-share/src/internals/test/LiveEventTarget.spec.ts similarity index 56% rename from packages/live-share/src/test/LiveEventTarget.spec.ts rename to packages/live-share/src/internals/test/LiveEventTarget.spec.ts index 5bb6dc052..435faf439 100644 --- a/packages/live-share/src/test/LiveEventTarget.spec.ts +++ b/packages/live-share/src/internals/test/LiveEventTarget.spec.ts @@ -4,12 +4,13 @@ */ import { strict as assert } from "assert"; -import { LiveEventScope } from "../LiveEventScope"; -import { LiveEventTarget } from "../LiveEventTarget"; -import { MockRuntimeSignaler } from "./MockRuntimeSignaler"; -import { LiveShareRuntime } from "../LiveShareRuntime"; -import { TestLiveShareHost } from "../TestLiveShareHost"; -import { LocalTimestampProvider } from "../LocalTimestampProvider"; +import { LiveEventScope } from "../LiveEventScope.js"; +import { LiveEventTarget } from "../LiveEventTarget.js"; +import { MockRuntimeSignaler } from "../mock/MockRuntimeSignaler.js"; +import { LiveShareRuntime } from "../LiveShareRuntime.js"; +import { TestLiveShareHost } from "../../TestLiveShareHost.js"; +import { LocalTimestampProvider } from "../../LocalTimestampProvider.js"; +import { MockTokenProvider } from "../mock/MockLiveShareRuntime.js"; function createConnectedSignalers() { const localRuntime = new MockRuntimeSignaler(); @@ -19,21 +20,33 @@ function createConnectedSignalers() { } describe("LiveEventTarget", () => { - let localLiveRuntime = new LiveShareRuntime(TestLiveShareHost.create(), { - timestampProvider: new LocalTimestampProvider(), - }); - let remoteLiveRuntime = new LiveShareRuntime(TestLiveShareHost.create(), { - timestampProvider: new LocalTimestampProvider(), - }); + let localLiveRuntime = new LiveShareRuntime( + TestLiveShareHost.create(new MockTokenProvider()), + { + timestampProvider: new LocalTimestampProvider(), + } + ); + let remoteLiveRuntime = new LiveShareRuntime( + TestLiveShareHost.create(new MockTokenProvider()), + { + timestampProvider: new LocalTimestampProvider(), + } + ); afterEach(async () => { // restore defaults - localLiveRuntime = new LiveShareRuntime(TestLiveShareHost.create(), { - timestampProvider: new LocalTimestampProvider(), - }); - remoteLiveRuntime = new LiveShareRuntime(TestLiveShareHost.create(), { - timestampProvider: new LocalTimestampProvider(), - }); + localLiveRuntime = new LiveShareRuntime( + TestLiveShareHost.create(new MockTokenProvider()), + { + timestampProvider: new LocalTimestampProvider(), + } + ); + remoteLiveRuntime = new LiveShareRuntime( + TestLiveShareHost.create(new MockTokenProvider()), + { + timestampProvider: new LocalTimestampProvider(), + } + ); }); it("Should receive events", (done) => { diff --git a/packages/live-share/src/test/LiveObjectSynchronizer.spec.ts b/packages/live-share/src/internals/test/LiveObjectSynchronizer.spec.ts similarity index 53% rename from packages/live-share/src/test/LiveObjectSynchronizer.spec.ts rename to packages/live-share/src/internals/test/LiveObjectSynchronizer.spec.ts index f94804fe2..297df0f28 100644 --- a/packages/live-share/src/test/LiveObjectSynchronizer.spec.ts +++ b/packages/live-share/src/internals/test/LiveObjectSynchronizer.spec.ts @@ -4,13 +4,14 @@ */ import { strict as assert } from "assert"; -import { LiveObjectSynchronizer } from "../LiveObjectSynchronizer"; -import { MockRuntimeSignaler } from "./MockRuntimeSignaler"; -import { Deferred, waitForDelay } from "../internals"; -import { MockLiveShareRuntime } from "./MockLiveShareRuntime"; +import { LiveObjectSynchronizer } from "../LiveObjectSynchronizer.js"; +import { MockRuntimeSignaler } from "../mock/MockRuntimeSignaler.js"; +import { Deferred } from "../Deferred.js"; +import { waitForDelay } from "../utils.js"; +import { MockLiveShareRuntime } from "../mock/MockLiveShareRuntime.js"; interface ITestState { - client: "local" | "remote"; + client: string; } describe("LiveObjectSynchronizer", () => { @@ -28,9 +29,9 @@ describe("LiveObjectSynchronizer", () => { localRuntime, localLiveRuntime ); - await localObject.start( - { client: "local" }, - async (state, sender) => { + await localObject.start({ + initialState: { client: "local" }, + updateState: async (state, sender) => { try { assert( typeof state.data == "object", @@ -47,8 +48,8 @@ describe("LiveObjectSynchronizer", () => { } return true; }, - () => Promise.resolve(true) - ); + getLocalUserCanSend: () => Promise.resolve(true), + }); const remoteRuntime = new MockRuntimeSignaler(); const remoteObject = new LiveObjectSynchronizer( @@ -56,11 +57,11 @@ describe("LiveObjectSynchronizer", () => { remoteRuntime, remoteLiveRuntime ); - await remoteObject.start( - { client: "remote" }, - (state, sender) => Promise.resolve(true), - () => Promise.resolve(true) - ); + await remoteObject.start({ + initialState: { client: "remote" }, + updateState: (state, sender) => Promise.resolve(true), + getLocalUserCanSend: () => Promise.resolve(true), + }); await done.promise; localObject.dispose(); @@ -83,9 +84,9 @@ describe("LiveObjectSynchronizer", () => { localRuntime, localLiveRuntime ); - await localObject.start( - { client: "local" }, - (state, sender) => { + await localObject.start({ + initialState: { client: "local" }, + updateState: (state, sender) => { try { assert( typeof state.data == "object", @@ -102,10 +103,10 @@ describe("LiveObjectSynchronizer", () => { } return Promise.resolve(true); }, - () => { + getLocalUserCanSend: () => { return Promise.resolve(true); - } - ); + }, + }); const remoteRuntime = new MockRuntimeSignaler(); const remoteObject = new LiveObjectSynchronizer( @@ -113,19 +114,19 @@ describe("LiveObjectSynchronizer", () => { remoteRuntime, remoteLiveRuntime ); - await remoteObject.start( - { client: "remote" }, - (state, sender) => { + await remoteObject.start({ + initialState: { client: "remote" }, + updateState: (state, sender) => { return Promise.resolve(true); }, - () => { + getLocalUserCanSend: () => { assert( remoteRuntime.connected, `remote: sending connect before connected` ); return Promise.resolve(true); - } - ); + }, + }); setTimeout(() => { localRuntime.connect(); @@ -155,9 +156,9 @@ describe("LiveObjectSynchronizer", () => { localRuntime, localLiveRuntime ); - await localObject.start( - { client: "local" }, - (state, sender) => { + await localObject.start({ + initialState: { client: "local" }, + updateState: (state, sender) => { try { assert( typeof state.data == "object", @@ -176,7 +177,7 @@ describe("LiveObjectSynchronizer", () => { } return Promise.resolve(true); }, - (connecting) => { + getLocalUserCanSend: (connecting) => { if (connecting) { // counting updates not connects return Promise.resolve(true); @@ -188,8 +189,8 @@ describe("LiveObjectSynchronizer", () => { } // If this is called, it will send out an update return Promise.resolve(true); - } - ); + }, + }); const remoteRuntime = new MockRuntimeSignaler(); const remoteObject = new LiveObjectSynchronizer( @@ -197,13 +198,13 @@ describe("LiveObjectSynchronizer", () => { remoteRuntime, remoteLiveRuntime ); - await remoteObject.start( - { client: "remote" }, - (state, sender) => { + await remoteObject.start({ + initialState: { client: "remote" }, + updateState: (state, sender) => { return Promise.resolve(true); }, - () => Promise.resolve(true) - ); + getLocalUserCanSend: () => Promise.resolve(true), + }); await done.promise; localObject.dispose(); @@ -227,13 +228,13 @@ describe("LiveObjectSynchronizer", () => { localRuntime, localLiveRuntime ); - await localObject.start( - { client: "local" }, - (state, sender) => { + await localObject.start({ + initialState: { client: "local" }, + updateState: (state, sender) => { done.reject(); return Promise.resolve(true); }, - (connecting) => { + getLocalUserCanSend: (connecting) => { if (connecting) { // counting updates not connects return Promise.resolve(true); @@ -246,9 +247,8 @@ describe("LiveObjectSynchronizer", () => { // If this is called, it will send out an update return Promise.resolve(true); }, - false, - false - ); + enableBackgroundUpdates: false, + }); const remoteRuntime = new MockRuntimeSignaler(); const remoteObject = new LiveObjectSynchronizer( @@ -256,15 +256,14 @@ describe("LiveObjectSynchronizer", () => { remoteRuntime, remoteLiveRuntime ); - await remoteObject.start( - { client: "remote" }, - (state, sender) => { + await remoteObject.start({ + initialState: { client: "remote" }, + updateState: (state, sender) => { return Promise.resolve(true); }, - () => Promise.resolve(true), - false, - false - ); + getLocalUserCanSend: () => Promise.resolve(true), + enableBackgroundUpdates: false, + }); await Promise.race([done.promise, waitForDelay(300)]); assert(sent == 0, `sent ${sent} updates when no updates was expected`); @@ -291,12 +290,12 @@ describe("LiveObjectSynchronizer", () => { localRuntime, localLiveRuntime ); - await localObject.start( - { client: "local" }, - (state, sender) => { + await localObject.start({ + initialState: { client: "local" }, + updateState: (state, sender) => { return Promise.resolve(true); }, - async (connecting) => { + getLocalUserCanSend: async (connecting) => { localSent++; if (connecting) { return true; @@ -309,8 +308,8 @@ describe("LiveObjectSynchronizer", () => { ); // If this is called, it will send out an update return true; - } - ); + }, + }); const remoteRuntime = new MockRuntimeSignaler(); const remoteObject = new LiveObjectSynchronizer( @@ -318,19 +317,19 @@ describe("LiveObjectSynchronizer", () => { remoteRuntime, remoteLiveRuntime ); - await remoteObject.start( - { client: "remote" }, - (state, sender) => { + await remoteObject.start({ + initialState: { client: "remote" }, + updateState: (state, sender) => { return Promise.resolve(true); }, - () => { + getLocalUserCanSend: () => { remoteSent++; if (remoteSent == 6) { done.resolve(); } return Promise.resolve(true); - } - ); + }, + }); await done.promise; localObject.dispose(); @@ -338,4 +337,169 @@ describe("LiveObjectSynchronizer", () => { localLiveRuntime.stop(); remoteLiveRuntime.stop(); }); + + it("Should only emit connect response to user that connected", async () => { + // We use targeted signals so that when a user first connects to LiveObjectSynchronizer, + // ach user responds back with their state only to the user that connects. + const localLiveRuntime = new MockLiveShareRuntime(true, 20); + const remoteLiveRuntime1 = new MockLiveShareRuntime(true, 20); + const remoteLiveRuntime2 = new MockLiveShareRuntime(true, 20); + localLiveRuntime.connectToOtherRuntime( + remoteLiveRuntime1, + remoteLiveRuntime2 + ); + await localLiveRuntime.start(); + await remoteLiveRuntime1.start(); + await remoteLiveRuntime2.start(); + + const localDone = new Deferred(); + const localRuntime = new MockRuntimeSignaler(); + const localObject = new LiveObjectSynchronizer( + "test", + localRuntime, + localLiveRuntime + ); + let localEmitCount = 0; + await localObject.start({ + initialState: { client: "local" }, + updateState: async (state) => { + if (localEmitCount === 0) { + // The first emit we receive the initial state for remote1 + try { + assert( + state.data.client == "remote1", + `local: invalid state received: ${state}` + ); + } catch (err) { + localDone.reject(err); + } + } else if (localEmitCount === 1) { + // The second emit we receive the initial state for remote2 + try { + assert( + state.data.client == "remote2", + `local: invalid state received: ${state}` + ); + localDone.resolve(); + } catch (err) { + localDone.reject(err); + } + } + + localEmitCount += 1; + + return false; + }, + getLocalUserCanSend: () => Promise.resolve(true), + }); + + await waitForDelay(5); + + const remote1Done = new Deferred(); + const remoteRuntime1 = new MockRuntimeSignaler(); + const remoteObject1 = new LiveObjectSynchronizer( + "test", + remoteRuntime1, + remoteLiveRuntime1 + ); + let remote1EmitCount = 0; + await remoteObject1.start({ + initialState: { client: "remote1" }, + updateState: async (state, sender) => { + if (remote1EmitCount === 0) { + // The first emit we receive a response to their connect event with local's current state. + try { + assert( + state.data.client == "local", + `local: invalid state received: ${state}` + ); + } catch (err) { + remote1Done.reject(err); + } + } else if (remote1EmitCount === 1) { + // The second emit we receive the initial state from remote2. + try { + assert( + state.data.client == "remote2", + `local: invalid state received: ${state}` + ); + remote1Done.resolve(); + } catch (err) { + remote1Done.reject(err); + } + } + remote1EmitCount += 1; + return false; + }, + getLocalUserCanSend: () => Promise.resolve(true), + }); + + await waitForDelay(5); + + const remote2Done = new Deferred(); + const remoteRuntime2 = new MockRuntimeSignaler(); + const remoteObject2 = new LiveObjectSynchronizer( + "test", + remoteRuntime2, + remoteLiveRuntime2 + ); + let remote2EmitCount = 0; + await remoteObject2.start({ + initialState: { client: "remote2" }, + updateState: async (state, sender) => { + if (remote2EmitCount === 0) { + // The first emit we receive a response to their connect event with local's current state. + try { + assert( + state.data.client == "local", + `local: invalid state received: ${state}` + ); + } catch (err) { + remote2Done.reject(err); + } + } else if (remote2EmitCount === 1) { + // The second emit we receive a response to their connect event with remote1's current state. + try { + assert( + state.data.client == "remote1", + `local: invalid state received: ${state}` + ); + remote2Done.resolve(); + } catch (err) { + remote2Done.reject(err); + } + } + remote2EmitCount += 1; + return false; + }, + getLocalUserCanSend: () => Promise.resolve(true), + }); + + await Promise.all([ + localDone.promise, + remote1Done.promise, + remote2Done.promise, + ]); + + await waitForDelay(10); + assert( + localEmitCount == 2, + `Local object should have only received 2 emits, instead received ${localEmitCount}` + ); + assert( + remote1EmitCount == 2, + `remote object 1 should have received 2 emits, instead received ${remote1EmitCount}` + ); + assert( + remote2EmitCount == 2, + `remote object 2 should have received 2 emits, instead received ${remote2EmitCount}` + ); + + localObject.dispose(); + remoteObject1.dispose(); + remoteObject2.dispose(); + localLiveRuntime.stop(); + remoteLiveRuntime1.stop(); + remoteLiveRuntime2.stop(); + }); }); diff --git a/packages/live-share/src/internals/type-guards.ts b/packages/live-share/src/internals/type-guards.ts index 0187b4856..6f9b8b41e 100644 --- a/packages/live-share/src/internals/type-guards.ts +++ b/packages/live-share/src/internals/type-guards.ts @@ -1,5 +1,12 @@ -import { TimestampProvider } from "../TimestampProvider"; -import { IClientInfo, ILiveEvent, UserMeetingRole } from "../interfaces"; +import { ITokenProvider } from "@fluidframework/azure-client"; +import { TestLiveShareHost } from "../TestLiveShareHost.js"; +import { TimestampProvider } from "../TimestampProvider.js"; +import { + IClientInfo, + ILiveEvent, + ILiveShareHost, + UserMeetingRole, +} from "../interfaces.js"; interface IMobileWorkaroundRolesResponse { userRoles: UserMeetingRole[]; @@ -48,6 +55,8 @@ export function isILiveEvent(value: any): value is ILiveEvent { return ( typeof value === "object" && typeof value.clientId === "string" && + (typeof value.targetClientId === "string" || + value.targetClientId === undefined) && typeof value.timestamp === "number" && typeof value.name === "string" ); @@ -59,3 +68,13 @@ export function isILiveEvent(value: any): value is ILiveEvent { export function isTimestampProvider(value: any): value is TimestampProvider { return typeof value?.start === "function"; } + +type HasInsecureTokenProvider = { + insecureTokenProvider: ITokenProvider; +}; + +export function isTestHostWithInsecureTokenProvider( + value: ILiveShareHost +): value is ILiveShareHost & HasInsecureTokenProvider { + return (value as any)?.insecureTokenProvider !== undefined; +} diff --git a/packages/live-share/src/internals/utils.ts b/packages/live-share/src/internals/utils.ts index 92b97afcb..203ff769a 100644 --- a/packages/live-share/src/internals/utils.ts +++ b/packages/live-share/src/internals/utils.ts @@ -3,9 +3,8 @@ * Licensed under the Microsoft Live Share SDK License. */ -import { ITokenProvider } from "@fluidframework/azure-client"; -import { v4 as uuid } from "uuid"; -import { IRuntimeSignaler } from "../LiveEventScope"; +import { IRuntimeSignaler } from "./LiveEventScope.js"; +import { IClientTimestamp } from "../interfaces.js"; /** * @hidden @@ -62,10 +61,7 @@ export function waitForResult( fnValidateResponse: (result: TRequestResult) => { response: TSuccessResult; } | null, - fnTimeout: (reason: unknown) => Error, retrySchedule: number[], - fnRequestError?: (error: unknown) => Error | null, - lateFinish?: () => void, basedDelayMilliseconds: number = 1000 ): Promise { let retries: number = 0; @@ -77,8 +73,7 @@ export function waitForResult( Math.max( basedDelayMilliseconds * (retries + 1), basedDelayMilliseconds * 3 - ), - lateFinish + ) ); const validated = fnValidateResponse(result); if (validated !== null) { @@ -90,17 +85,9 @@ export function waitForResult( } } catch (error: unknown) { if (retries >= retrySchedule.length) { - reject(fnTimeout(error)); + reject(error); break; } - // Check if this error is something that should cause us to skip the retry schedule - if (!!fnRequestError && !(error instanceof TimeoutError)) { - const rejectNowError = fnRequestError(error); - if (rejectNowError !== null) { - reject(rejectNowError); - break; - } - } } await waitForDelay(retrySchedule[retries++]); @@ -114,54 +101,23 @@ export function waitForResult( */ export function timeoutRequest( fnRequest: () => Promise, - timeout: number, - lateFinish?: () => void + timeout: number ): Promise { return new Promise(async (resolve, reject) => { - let hTimer: NodeJS.Timeout | null = setTimeout(() => { + let hTimer: any = setTimeout(() => { reject(new TimeoutError()); hTimer = null; }, timeout); try { const result = await fnRequest(); resolve(result); - if (hTimer == null) { - lateFinish?.(); - } } catch (error: unknown) { reject(error); - if (hTimer == null) { - lateFinish?.(); - } } clearTimeout(hTimer); }); } -/** - * Dynamically import InsecureTokenProvider class, in case developer does not yet have "@fluidframework/test-client-utils", - * since don't want to require that they include it in package.json. - * @hidden - */ -export async function getInsecureTokenProvider(): Promise { - try { - const { InsecureTokenProvider } = - await require("@fluidframework/test-client-utils"); - const userIdParam = new URL(window.location.href)?.searchParams?.get( - "userId" - ); - const tokenProvider = new InsecureTokenProvider("", { - id: userIdParam ?? uuid(), - name: "Test User", - }); - return tokenProvider as ITokenProvider; - } catch { - throw new Error( - "@microsoft/live-share: when using 'local' connection type, you must have @fluidframework/test-client-utils installed" - ); - } -} - /** * @hidden * Waits until connected and gets the most recent clientId @@ -181,3 +137,62 @@ export function waitUntilConnected(runtime: IRuntimeSignaler): Promise { } }); } + +/** + * @hidden + * Returns true if a received event is newer then the current event. + * + * @remarks + * Used when building new Live objects to process state change events. The `isNewer()` + * method implements an algorithm that deals with conflicting events that have the same timestamp + * and older events that should have debounced the current event. + * + * - When the received event has the same timestamp as the current event, each events clientId + * will be used as a tie breaker. The clientId containing the lower sort order wins any ties. + * - Older events are generally ignored unless a debounce period is specified. An older event + * that should have debounced the current event will be considered newer. + * + * The algorithm employed by isNewer() helps ensure that all clients will eventually reach a + * consistent state with one other. + * @param current Current event to compare received event against. + * @param received Received event. + * @param debouncePeriod Optional. Time in milliseconds to ignore any new events for. Defaults to 0 ms. + * @returns True if the received event is newer then the current event and should replace the current one. + */ +export function isNewerEvent( + current: IClientTimestamp | undefined, + received: IClientTimestamp, + debouncePeriod = 0 +): boolean { + if (current) { + if (current.timestamp == received.timestamp) { + // In a case where both clientId's are blank that's the local client in a disconnected state + const cmp = (current.clientId || "").localeCompare( + received.clientId || "" + ); + if (cmp <= 0) { + // - cmp == 0 is same user. We use to identify events for same user as newer but + // that was causing us to fire duplicate state & presence change events. The better + // approach is to update the timestamp provider to never return the same timestamp + // twice. (Comparison was changed on 8/2/2022) + // - cmp > 0 is a tie breaker so we'll take that event as well (comparing 'a' with 'c' + // will result in a negative value). + return false; + } + } else if (current.timestamp > received.timestamp) { + // Did we receive an older event that should have caused us to debounce the current one? + const delta = current.timestamp - received.timestamp; + if (delta > debouncePeriod) { + return false; + } + } else { + // Is the new event within the debounce period? + const delta = received.timestamp - current.timestamp; + if (delta < debouncePeriod) { + return false; + } + } + } + + return true; +} diff --git a/packages/live-share/src/test/.mocharc.js b/packages/live-share/src/test/.mocharc.js deleted file mode 100644 index 28b840eb9..000000000 --- a/packages/live-share/src/test/.mocharc.js +++ /dev/null @@ -1,12 +0,0 @@ -/*! - * Copyright (c) Microsoft Corporation and contributors. All rights reserved. - * Licensed under the Microsoft Live Share SDK License. - */ - -'use strict'; - -const packageDir = `${__dirname}/../..`; - -const getFluidTestMochaConfig = require("@fluidframework/mocha-test-setup/mocharc-common.js"); -const config = getFluidTestMochaConfig(packageDir); -module.exports = config; diff --git a/packages/live-share-turbo/src/test/AzureTurboClient.spec.ts b/packages/live-share/src/test/AzureLiveShareClient.spec.ts similarity index 74% rename from packages/live-share-turbo/src/test/AzureTurboClient.spec.ts rename to packages/live-share/src/test/AzureLiveShareClient.spec.ts index e7184af73..f372b2c4b 100644 --- a/packages/live-share-turbo/src/test/AzureTurboClient.spec.ts +++ b/packages/live-share/src/test/AzureLiveShareClient.spec.ts @@ -4,60 +4,66 @@ */ import { strict as assert } from "assert"; -import { - IFluidContainer, - LoadableObjectClassRecord, - SharedMap, -} from "fluid-framework"; +import { ContainerSchema, IFluidContainer } from "fluid-framework"; +import { SharedMap } from "fluid-framework/legacy"; + import { AzureContainerServices, AzureLocalConnectionConfig, } from "@fluidframework/azure-client"; -import { AzureTurboClient } from "../AzureTurboClient"; -import { InsecureTokenProvider } from "@fluidframework/test-client-utils"; -import { generateUser } from "@fluidframework/server-services-client"; -import { LiveEvent } from "@microsoft/live-share"; +import { AzureLiveShareClient } from "../AzureLiveShareClient.js"; +import { + IInsecureUser, + InsecureTokenProvider, +} from "@fluidframework/test-runtime-utils/internal"; +import { LiveEvent } from "../LiveEvent.js"; +import { LiveState } from "../LiveState.js"; +import { v4 as uuid } from "uuid"; -describe("AzureTurboClient", () => { - (window.performance as any).mark = () => { - return {}; - }; - (window.performance as any).measure = () => { - return {}; +function generateUser(): IInsecureUser { + const randomUser = { + id: uuid(), + name: uuid(), }; + return randomUser; +} + +describe("AzureTurboClient", () => { const connectionProps: AzureLocalConnectionConfig = { tokenProvider: new InsecureTokenProvider("fooBar", generateUser()), endpoint: "http://localhost:7070", type: "local", }; - let client1: AzureTurboClient; - let client2: AzureTurboClient; + let client1: AzureLiveShareClient; + let client2: AzureLiveShareClient; const testMapKey = "TEST-MAP-KEY"; const testLiveEventKey = "TEST-LIVE-EVENT-KEY"; + const schema = { + initialObjects: { + [testLiveEventKey]: LiveEvent, + }, + } as const satisfies ContainerSchema; let results1: { - container: IFluidContainer; + container: IFluidContainer; services: AzureContainerServices; }; let results2: { - container: IFluidContainer; + container: IFluidContainer; services: AzureContainerServices; }; beforeEach(async () => { - client1 = new AzureTurboClient({ + client1 = new AzureLiveShareClient({ connection: connectionProps, }); - client2 = new AzureTurboClient({ + client2 = new AzureLiveShareClient({ connection: connectionProps, }); - const initialObjects: LoadableObjectClassRecord = { - [testLiveEventKey]: LiveEvent, - }; - results1 = await client1.createContainer(initialObjects); + results1 = await client1.createContainer(schema); const containerId = await results1.container.attach(); - results2 = await client2.getContainer(containerId, initialObjects); + results2 = await client2.getContainer(containerId, schema); }); it("Containers should be configured correctly", async () => { @@ -69,6 +75,10 @@ describe("AzureTurboClient", () => { !!results1.container || !!results1.services, "client1 results container or services are not defined" ); + + // state map not initialized until dynamic features are used. + await client1.getDDS("test", LiveState); + await client2.getDDS("test", LiveState); assert( !!client1.stateMap || !!client2.stateMap, "stateMap is not defined" @@ -108,10 +118,10 @@ describe("AzureTurboClient", () => { dds1 !== undefined && dds2 !== undefined, "test map(s) not defined" ); - // Only one should be marked as created + // two should be marked as created, one gets discarded after consensus is reached assert( [object1Created, object2Created].filter((created) => created) - .length === 1, + .length === 2, "Incorrect number of objects created" ); }); diff --git a/packages/live-share/src/test/LiveEvent.spec.ts b/packages/live-share/src/test/LiveEvent.spec.ts index 31f25a00f..12f6cbb2b 100644 --- a/packages/live-share/src/test/LiveEvent.spec.ts +++ b/packages/live-share/src/test/LiveEvent.spec.ts @@ -4,306 +4,437 @@ */ import { strict as assert } from "assert"; -import { requestFluidObject } from "@fluidframework/runtime-utils"; -import { ITestObjectProvider } from "@fluidframework/test-utils"; -import { describeNoCompat } from "@fluidframework/test-version-utils"; -import { LiveEvent } from "../LiveEvent"; -import { Deferred } from "../internals"; -import { MockTimestampProvider } from "./MockTimestampProvider"; -import { MockRoleVerifier } from "./MockRoleVerifier"; -import { LocalTimestampProvider } from "../LocalTimestampProvider"; -import { UserMeetingRole, ILiveEvent } from "../interfaces"; -import { TestLiveShareHost } from "../TestLiveShareHost"; -import { getLiveDataObjectClass } from "../schema-injection-utils"; -import { LiveShareRuntime } from "../LiveShareRuntime"; -import { DataObjectClass } from "fluid-framework"; - -describeNoCompat("LiveEvent", (getTestObjectProvider) => { - let provider: ITestObjectProvider; - let object1: LiveEvent; - let object2: LiveEvent; - let liveRuntime1: LiveShareRuntime = new LiveShareRuntime( - TestLiveShareHost.create(), - { - timestampProvider: new LocalTimestampProvider(), - } - ); - let LiveEventProxy1 = getLiveDataObjectClass( - LiveEvent, - liveRuntime1 - ) as DataObjectClass; - let liveRuntime2: LiveShareRuntime = new LiveShareRuntime( - TestLiveShareHost.create(), - { - timestampProvider: new LocalTimestampProvider(), - } - ); - let LiveEventProxy2 = getLiveDataObjectClass( - LiveEvent, - liveRuntime2 - ) as DataObjectClass; - - beforeEach(async () => { - provider = getTestObjectProvider(); - const container1 = await provider.createContainer( - LiveEventProxy1.factory +import { + ITestObjectProvider, + fluidEntryPoint, + getContainerEntryPointBackCompat, +} from "@fluidframework/test-utils/internal"; +import { LiveEvent } from "../LiveEvent.js"; +import { MockTimestampProvider } from "../internals/mock/MockTimestampProvider.js"; +import { MockRoleVerifier } from "../internals/mock/MockRoleVerifier.js"; +import { LocalTimestampProvider } from "../LocalTimestampProvider.js"; +import { UserMeetingRole, ILiveEvent } from "../interfaces.js"; +import { TestLiveShareHost } from "../TestLiveShareHost.js"; +import { getLiveDataObjectKind } from "../internals/schema-injection-utils.js"; +import { LiveShareRuntime } from "../internals/LiveShareRuntime.js"; +import { + describeCompat, + ITestObjectProviderOptions, +} from "@live-share-private/test-utils"; +import { Deferred } from "../internals/Deferred.js"; +import { isNewerEvent, waitForDelay } from "../internals/utils.js"; +import { MockTokenProvider } from "../internals/mock/MockLiveShareRuntime.js"; + +describeCompat( + "LiveEvent", + ( + getTestObjectProvider: ( + options?: ITestObjectProviderOptions + ) => ITestObjectProvider + ) => { + let provider: ITestObjectProvider; + let object1: LiveEvent; + let object2: LiveEvent; + let object3: LiveEvent; + let liveRuntime1: LiveShareRuntime = new LiveShareRuntime( + TestLiveShareHost.create(new MockTokenProvider()), + { + timestampProvider: new LocalTimestampProvider(), + } ); - object1 = await requestFluidObject(container1, "default"); - - const container2 = await provider.loadContainer( - LiveEventProxy2.factory + let LiveEventProxy1: any = getLiveDataObjectKind( + LiveEvent, + liveRuntime1 + ); + let liveRuntime2: LiveShareRuntime = new LiveShareRuntime( + TestLiveShareHost.create(new MockTokenProvider()), + { + timestampProvider: new LocalTimestampProvider(), + } + ); + let LiveEventProxy2: any = getLiveDataObjectKind( + LiveEvent, + liveRuntime2 + ); + let liveRuntime3: LiveShareRuntime = new LiveShareRuntime( + TestLiveShareHost.create(new MockTokenProvider()), + { + timestampProvider: new LocalTimestampProvider(), + } ); - object2 = await requestFluidObject(container2, "default"); + let LiveEventProxy3: any = getLiveDataObjectKind( + LiveEvent, + liveRuntime3 + ); + + beforeEach(async () => { + provider = getTestObjectProvider(); + + const container1 = await provider.createContainer( + LiveEventProxy1.factory as fluidEntryPoint + ); + object1 = + await getContainerEntryPointBackCompat(container1); - // need to be connected to send signals - if (!container1.connect) { - await new Promise((resolve) => - container1.once("connected", resolve) + const container2 = await provider.loadContainer( + LiveEventProxy2.factory as fluidEntryPoint ); - } - if (!container2.connect) { - await new Promise((resolve) => - container2.once("connected", resolve) + object2 = + await getContainerEntryPointBackCompat(container2); + + const container3 = await provider.loadContainer( + LiveEventProxy3.factory as fluidEntryPoint ); - } - }); - - afterEach(async () => { - // restore defaults - liveRuntime1.setTimestampProvider(new LocalTimestampProvider()); - liveRuntime2.setTimestampProvider(new LocalTimestampProvider()); - }); - - it("Should raise local and remote events", async () => { - const now = new Date().getTime(); - const object1done = new Deferred(); - object1.on("received", (evt, local, clientId, timestamp) => { + object3 = + await getContainerEntryPointBackCompat(container3); + + // need to be connected to send signals + if (!container1.connect) { + await new Promise((resolve) => + container1.once("connected", resolve) + ); + } + if (!container2.connect) { + await new Promise((resolve) => + container2.once("connected", resolve) + ); + } + if (!container3.connect) { + await new Promise((resolve) => + container2.once("connected", resolve) + ); + } + }); + + afterEach(async () => { + // restore defaults + liveRuntime1.setTimestampProvider(new LocalTimestampProvider()); + liveRuntime2.setTimestampProvider(new LocalTimestampProvider()); + liveRuntime3.setTimestampProvider(new LocalTimestampProvider()); + }); + + it("Should raise local and remote events", async () => { + const now = new Date().getTime(); + const object1done = new Deferred(); + object1.on("received", (evt, local, clientId, timestamp) => { + try { + assert(local == true, `Not a local event`); + assert(evt != null, `Null event arg`); + assert(clientId != null, `Missing clientId`); + assert(typeof timestamp == "number", `Missing timestamp`); + assert(timestamp >= now, `Timestamp too old`); + object1done.resolve(); + } catch (err) { + object1done.reject(err); + } + }); + await object1.initialize(); + + const object2done = new Deferred(); + object2.on("received", (evt, local, clientId, timestamp) => { + try { + assert(local == false, `Unexpected local event`); + assert(evt != null, `Null event arg`); + assert(clientId != null, `Missing clientId`); + assert(typeof timestamp == "number", `Missing timestamp`); + assert(timestamp >= now, `Timestamp too old`); + object2done.resolve(); + } catch (err) { + object2done.reject(err); + } + }); + await object2.initialize(); + + object1.send({}); + + // Wait for events to trigger + await Promise.all([object1done.promise, object2done.promise]); + }); + + it("Should throw error if already started", async () => { + await object1.initialize(); try { - assert(local == true, `Not a local event`); - assert(evt != null, `Null event arg`); - assert(clientId != null, `Missing clientId`); - assert(typeof timestamp == "number", `Missing timestamp`); - assert(timestamp >= now, `Timestamp too old`); - object1done.resolve(); + // Ensure started + assert(object1.isInitialized, `not started`); + + // Try second call to initialize. + await object1.initialize(); + assert(false, `exception not thrown`); } catch (err) { - object1done.reject(err); + console.error("There was an error"); } }); - await object1.initialize(); - const object2done = new Deferred(); - object2.on("received", (evt, local, clientId, timestamp) => { + it("Should throw error if sendEvent() called before start", async () => { try { - assert(local == false, `Unexpected local event`); - assert(evt != null, `Null event arg`); - assert(clientId != null, `Missing clientId`); - assert(typeof timestamp == "number", `Missing timestamp`); - assert(timestamp >= now, `Timestamp too old`); - object2done.resolve(); + await object1.send({}); + assert(false, `exception not thrown`); } catch (err) { - object2done.reject(err); + console.error("There was an error"); } }); - await object2.initialize(); - object1.send({}); + it("Should getTimestamp() using local timestamp provider", () => { + const now = new Date().getTime(); + const timestamp = liveRuntime1.getTimestamp(); + assert(timestamp >= now); + }); + + it("Should getTimestamp() using custom timestamp providers", async () => { + const mock = new MockTimestampProvider(); + const customRuntime = new LiveShareRuntime( + TestLiveShareHost.create(new MockTokenProvider()), + { + timestampProvider: mock, + } + ); - // Wait for events to trigger - await Promise.all([object1done.promise, object2done.promise]); - }); + const now = new Date().getTime(); + const timestamp = customRuntime.getTimestamp(); + assert(timestamp >= now, `Unexpected timestamp value`); + assert(mock.called, `Mock not called`); + }); - it("Should throw error if already started", async () => { - await object1.initialize(); - try { - // Ensure started - assert(object1.isInitialized, `not started`); + it("Should verifyRolesAllowed() using local role verifier", async () => { + const allowed = await liveRuntime1.verifyRolesAllowed("test", [ + UserMeetingRole.presenter, + ]); + assert(allowed, `Role should be allowed`); + }); - // Try second call to initialize. - await object1.initialize(); - assert(false, `exception not thrown`); - } catch (err) { - console.error("There was an error"); - } - }); - - it("Should throw error if sendEvent() called before start", async () => { - try { - await object1.send({}); - assert(false, `exception not thrown`); - } catch (err) { - console.error("There was an error"); - } - }); - - it("Should getTimestamp() using local timestamp provider", () => { - const now = new Date().getTime(); - const timestamp = liveRuntime1.getTimestamp(); - assert(timestamp >= now); - }); - - it("Should getTimestamp() using custom timestamp providers", async () => { - const mock = new MockTimestampProvider(); - const customRuntime = new LiveShareRuntime(TestLiveShareHost.create(), { - timestampProvider: mock, + it("Should verifyRolesAllowed() using custom role verifier", async () => { + const mock = new MockRoleVerifier([UserMeetingRole.presenter]); + const customRuntime = new LiveShareRuntime( + TestLiveShareHost.create(new MockTokenProvider()), + { + roleVerifier: mock, + } + ); + + const allowed = await customRuntime.verifyRolesAllowed("test", [ + UserMeetingRole.presenter, + ]); + assert(allowed, `Role should be allowed`); + assert(mock.called, `mock not called`); + assert( + mock.clientId == "test", + `Invalid clientId of ${mock.clientId}` + ); + }); + + it("Should allow newer received events", () => { + const current: ILiveEvent = { + name: "test", + clientId: "CA", + timestamp: 1000, + data: undefined, + }; + + const received: ILiveEvent = { + name: "test", + clientId: "CB", + timestamp: 1001, + data: undefined, + }; + + const allowed = isNewerEvent(current, received); + assert(allowed, `event blocked`); + }); + + it("Should block older received events", () => { + const current: ILiveEvent = { + name: "test", + clientId: "CA", + timestamp: 1000, + data: undefined, + }; + + const received: ILiveEvent = { + name: "test", + clientId: "CB", + timestamp: 999, + data: undefined, + }; + + const allowed = isNewerEvent(current, received); + assert(!allowed, `event allowed`); + }); + + it("Should block events with same timestamp from same client", () => { + const current: ILiveEvent = { + name: "test", + clientId: "CA", + timestamp: 1000, + data: undefined, + }; + + const received: ILiveEvent = { + name: "test", + clientId: "CA", + timestamp: 1000, + data: undefined, + }; + + const allowed = isNewerEvent(current, received); + assert(!allowed, `event allowed`); + }); + + it("Should allow events with same timestamp and a different clientId that sorts lower", () => { + const current: ILiveEvent = { + name: "test", + clientId: "CB", + timestamp: 1000, + data: undefined, + }; + + const received: ILiveEvent = { + name: "test", + clientId: "CA", + timestamp: 1000, + data: undefined, + }; + + const allowed = isNewerEvent(current, received); + assert(allowed, `event blocked`); + }); + + it("Should block events with same timestamp and a different clientId that sorts higher", () => { + const current: ILiveEvent = { + name: "test", + clientId: "CA", + timestamp: 1000, + data: undefined, + }; + + const received: ILiveEvent = { + name: "test", + clientId: "CB", + timestamp: 1000, + data: undefined, + }; + + const allowed = isNewerEvent(current, received); + assert(!allowed, `event allowed`); + }); + + it("Should debounce newer events", () => { + const current: ILiveEvent = { + name: "test", + clientId: "CA", + timestamp: 1000, + data: undefined, + }; + + const received: ILiveEvent = { + name: "test", + clientId: "CB", + timestamp: 1050, + data: undefined, + }; + + const allowed = isNewerEvent(current, received, 100); + assert(!allowed, `event allowed`); }); - const now = new Date().getTime(); - const timestamp = customRuntime.getTimestamp(); - assert(timestamp >= now, `Unexpected timestamp value`); - assert(mock.called, `Mock not called`); - }); - - it("Should verifyRolesAllowed() using local role verifier", async () => { - const allowed = await liveRuntime1.verifyRolesAllowed("test", [ - UserMeetingRole.presenter, - ]); - assert(allowed, `Role should be allowed`); - }); - - it("Should verifyRolesAllowed() using custom role verifier", async () => { - const mock = new MockRoleVerifier([UserMeetingRole.presenter]); - const customRuntime = new LiveShareRuntime(TestLiveShareHost.create(), { - roleVerifier: mock, + it("Should allow older events that would have debounced the current event", () => { + const current: ILiveEvent = { + name: "test", + clientId: "CA", + timestamp: 1000, + data: undefined, + }; + + const received: ILiveEvent = { + name: "test", + clientId: "CB", + timestamp: 950, + data: undefined, + }; + + const allowed = isNewerEvent(current, received, 100); + assert(allowed, `event blocked`); }); - const allowed = await customRuntime.verifyRolesAllowed("test", [ - UserMeetingRole.presenter, - ]); - assert(allowed, `Role should be allowed`); - assert(mock.called, `mock not called`); - assert(mock.clientId == "test", `Invalid clientId of ${mock.clientId}`); - }); - - it("Should allow newer received events", () => { - const current: ILiveEvent = { - name: "test", - clientId: "CA", - timestamp: 1000, - data: undefined, - }; - - const received: ILiveEvent = { - name: "test", - clientId: "CB", - timestamp: 1001, - data: undefined, - }; - - const allowed = LiveEvent.isNewer(current, received); - assert(allowed, `event blocked`); - }); - - it("Should block older received events", () => { - const current: ILiveEvent = { - name: "test", - clientId: "CA", - timestamp: 1000, - data: undefined, - }; - - const received: ILiveEvent = { - name: "test", - clientId: "CB", - timestamp: 999, - data: undefined, - }; - - const allowed = LiveEvent.isNewer(current, received); - assert(!allowed, `event allowed`); - }); - - it("Should block events with same timestamp from same client", () => { - const current: ILiveEvent = { - name: "test", - clientId: "CA", - timestamp: 1000, - data: undefined, - }; - - const received: ILiveEvent = { - name: "test", - clientId: "CA", - timestamp: 1000, - data: undefined, - }; - - const allowed = LiveEvent.isNewer(current, received); - assert(!allowed, `event allowed`); - }); - - it("Should allow events with same timestamp and a different clientId that sorts lower", () => { - const current: ILiveEvent = { - name: "test", - clientId: "CB", - timestamp: 1000, - data: undefined, - }; - - const received: ILiveEvent = { - name: "test", - clientId: "CA", - timestamp: 1000, - data: undefined, - }; - - const allowed = LiveEvent.isNewer(current, received); - assert(allowed, `event blocked`); - }); - - it("Should block events with same timestamp and a different clientId that sorts higher", () => { - const current: ILiveEvent = { - name: "test", - clientId: "CA", - timestamp: 1000, - data: undefined, - }; - - const received: ILiveEvent = { - name: "test", - clientId: "CB", - timestamp: 1000, - data: undefined, - }; - - const allowed = LiveEvent.isNewer(current, received); - assert(!allowed, `event allowed`); - }); - - it("Should debounce newer events", () => { - const current: ILiveEvent = { - name: "test", - clientId: "CA", - timestamp: 1000, - data: undefined, - }; - - const received: ILiveEvent = { - name: "test", - clientId: "CB", - timestamp: 1050, - data: undefined, - }; - - const allowed = LiveEvent.isNewer(current, received, 100); - assert(!allowed, `event allowed`); - }); - - it("Should allow older events that would have debounced the current event", () => { - const current: ILiveEvent = { - name: "test", - clientId: "CA", - timestamp: 1000, - data: undefined, - }; - - const received: ILiveEvent = { - name: "test", - clientId: "CB", - timestamp: 950, - data: undefined, - }; - - const allowed = LiveEvent.isNewer(current, received, 100); - assert(allowed, `event blocked`); - }); -}); + it("Targeting specific clients should only emit updates to the target client", async () => { + let object1ClientId: string; + let object2ClientId: string; + let object3ClientId: string; + + const object1done = new Deferred(); + object1.on("received", (evt, local, clientId, timestamp) => { + try { + assert(local == true, `Not a local event`); + assert( + clientId === object1ClientId, + `Unexpected clientId ${clientId}, should be local object1ClientId ${object1ClientId}` + ); + object1done.resolve(); + } catch (err) { + object1done.reject(err); + } + }); + await object1.initialize(); + + const object2done = new Deferred(); + let emitCount = 0; + object2.on("received", (evt, local, clientId, timestamp) => { + if (emitCount === 0) { + try { + assert(local == false, `Unexpected local event`); + assert( + clientId === object1ClientId, + `Unexpected clientId ${clientId}, should be remote object1ClientId ${object1ClientId}` + ); + } catch (err) { + object2done.reject(err); + } + } else if (emitCount === 1) { + try { + assert(local == true, `Not a local event`); + assert( + clientId === object2ClientId, + `Unexpected clientId ${clientId}, should be local object2ClientId ${object2ClientId}` + ); + object2done.resolve(); + } catch (err) { + object2done.reject(err); + } + } + emitCount += 1; + }); + await object2.initialize(); + + const object3done = new Deferred(); + object3.on("received", (evt, local, clientId, timestamp) => { + try { + assert(local == false, `Unexpected local event`); + assert( + clientId === object2ClientId, + `Unexpected clientId ${clientId}, should be remote object2ClientId ${object2ClientId}` + ); + object3done.resolve(); + } catch (err) { + object3done.reject(err); + } + }); + await object3.initialize(); + + // @ts-ignore-next-line + object1ClientId = object1.runtime.clientId; + // @ts-ignore-next-line + object2ClientId = object2.runtime.clientId; + // @ts-ignore-next-line + object3ClientId = object3.runtime.clientId; + + await object1.send({}, object2ClientId); + await object2.send({}, object3ClientId); + + // Wait for events to trigger + await Promise.all([ + object1done.promise, + object2done.promise, + object3done.promise, + ]); + }); + } +); diff --git a/packages/live-share/src/test/LiveEventTimer.spec.ts b/packages/live-share/src/test/LiveEventTimer.spec.ts deleted file mode 100644 index 1a94f12ba..000000000 --- a/packages/live-share/src/test/LiveEventTimer.spec.ts +++ /dev/null @@ -1,130 +0,0 @@ -/*! - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Microsoft Live Share SDK License. - */ - -import { strict as assert } from "assert"; -import { LiveEventScope } from "../LiveEventScope"; -import { LiveEventTarget } from "../LiveEventTarget"; -import { LiveEventTimer } from "../LiveEventTimer"; -import { MockRuntimeSignaler } from "./MockRuntimeSignaler"; -import { LiveShareRuntime } from "../LiveShareRuntime"; -import { TestLiveShareHost } from "../TestLiveShareHost"; -import { LocalTimestampProvider } from "../LocalTimestampProvider"; - -function createConnectedSignalers() { - const localRuntime = new MockRuntimeSignaler(); - const remoteRuntime = new MockRuntimeSignaler(); - MockRuntimeSignaler.connectRuntimes([localRuntime, remoteRuntime]); - return { localRuntime, remoteRuntime }; -} - -describe("LiveEventTimer", () => { - let localLiveRuntime = new LiveShareRuntime(TestLiveShareHost.create(), { - timestampProvider: new LocalTimestampProvider(), - }); - let remoteLiveRuntime = new LiveShareRuntime(TestLiveShareHost.create(), { - timestampProvider: new LocalTimestampProvider(), - }); - - afterEach(async () => { - // restore defaults - localLiveRuntime = new LiveShareRuntime(TestLiveShareHost.create(), { - timestampProvider: new LocalTimestampProvider(), - }); - remoteLiveRuntime = new LiveShareRuntime(TestLiveShareHost.create(), { - timestampProvider: new LocalTimestampProvider(), - }); - }); - - it("Should send a single event after a delay", (done) => { - let created = 0; - let triggered = 0; - const signalers = createConnectedSignalers(); - const localScope = new LiveEventScope( - signalers.localRuntime, - localLiveRuntime - ); - const localTarget = new LiveEventTarget<{}>( - localScope, - "test", - (evt, local) => triggered++ - ); - const localTimer = new LiveEventTimer( - localTarget, - () => { - created++; - return {}; - }, - 10 - ); - - const remoteScope = new LiveEventScope( - signalers.remoteRuntime, - remoteLiveRuntime - ); - const remoteTarget = new LiveEventTarget( - remoteScope, - "test", - (evt, local) => triggered++ - ); - - localTimer.start(); - assert(created == 0); - setTimeout(() => { - assert(created == 1, `Message creation count is ${created}`); - assert( - triggered == created * 2, - `Messages created is ${created} but received is an unexpected ${triggered}` - ); - localTimer.stop(); - done(); - }, 50); - }); - - it("Should repeatedly send events after a delay", (done) => { - let created = 0; - let triggered = 0; - const signalers = createConnectedSignalers(); - const localScope = new LiveEventScope( - signalers.localRuntime, - localLiveRuntime - ); - const localTarget = new LiveEventTarget<{}>( - localScope, - "test", - (evt, local) => triggered++ - ); - const localTimer = new LiveEventTimer( - localTarget, - () => { - created++; - return {}; - }, - 5, - true - ); - - const remoteScope = new LiveEventScope( - signalers.remoteRuntime, - remoteLiveRuntime - ); - const remoteTarget = new LiveEventTarget( - remoteScope, - "test", - (evt, local) => triggered++ - ); - - localTimer.start(); - assert(created == 0); - setTimeout(() => { - assert(created > 1, `Message creation count is ${created}`); - assert( - triggered == created * 2, - `Messages created is ${created} but received is an unexpected ${triggered}` - ); - localTimer.stop(); - done(); - }, 50); - }); -}); diff --git a/packages/live-share/src/test/LiveFollowMode.spec.ts b/packages/live-share/src/test/LiveFollowMode.spec.ts index 5f0eba9cd..cff4034cb 100644 --- a/packages/live-share/src/test/LiveFollowMode.spec.ts +++ b/packages/live-share/src/test/LiveFollowMode.spec.ts @@ -4,33 +4,44 @@ */ import { strict as assert } from "assert"; -import { requestFluidObject } from "@fluidframework/runtime-utils"; -import { ITestObjectProvider } from "@fluidframework/test-utils"; -import { describeNoCompat } from "@fluidframework/test-version-utils"; +import { + ITestObjectProvider, + fluidEntryPoint, + getContainerEntryPointBackCompat, +} from "@fluidframework/test-utils/internal"; import { FollowModeType, IFollowModePresenceUserData, IFollowModeState, LiveFollowMode, -} from "../LiveFollowMode"; -import { Deferred, waitForDelay } from "../internals"; -import { getLiveDataObjectClass } from "../schema-injection-utils"; -import { MockLiveShareRuntime } from "./MockLiveShareRuntime"; -import { LivePresenceUser } from "../LivePresenceUser"; +} from "../LiveFollowMode.js"; +import { getLiveDataObjectKind } from "../internals/schema-injection-utils.js"; +import { MockLiveShareRuntime } from "../internals/mock/MockLiveShareRuntime.js"; +import { LivePresenceUser } from "../LivePresenceUser.js"; +import { + describeCompat, + ITestObjectProviderOptions, +} from "@live-share-private/test-utils"; +import { waitForDelay } from "../internals/utils.js"; +import { Deferred } from "../internals/Deferred.js"; interface TestFollowData { page: string; } -async function getObjects(getTestObjectProvider) { +async function getObjects( + getTestObjectProvider: ( + options?: ITestObjectProviderOptions + ) => ITestObjectProvider +) { // Temporarily change update interval let liveRuntime1 = new MockLiveShareRuntime(false); let liveRuntime2 = new MockLiveShareRuntime(false); - let ObjectProxy1: any = getLiveDataObjectClass< + let ObjectProxy1: any = getLiveDataObjectKind< LiveFollowMode >(LiveFollowMode, liveRuntime1); - let ObjectProxy2: any = getLiveDataObjectClass< + let ObjectProxy2: any = getLiveDataObjectKind< LiveFollowMode >(LiveFollowMode, liveRuntime2); @@ -39,17 +50,18 @@ async function getObjects(getTestObjectProvider) { let provider: ITestObjectProvider = getTestObjectProvider(); - let container1 = await provider.createContainer(ObjectProxy1.factory); - let object1 = await requestFluidObject>( - container1, - "default" + let container1 = await provider.createContainer( + ObjectProxy1.factory as fluidEntryPoint ); + let object1 = + await getContainerEntryPointBackCompat(container1); - let container2 = await provider.loadContainer(ObjectProxy2.factory); - let object2 = await requestFluidObject>( - container2, - "default" + let container2 = await provider.loadContainer( + ObjectProxy2.factory as fluidEntryPoint ); + let object2 = + await getContainerEntryPointBackCompat(container2); + // need to be connected to send signals if (!container1.connect) { await new Promise((resolve) => container1.once("connected", resolve)); @@ -76,410 +88,423 @@ const mockDefaultValue: TestFollowData = { page: "foo", }; -describeNoCompat("LiveFollowMode", (getTestObjectProvider) => { - it("Should initialize with correct defaults", async () => { - const { object1, object2, dispose } = await getObjects( - getTestObjectProvider - ); - let init1 = object1.initialize(mockDefaultValue); - let init2 = object2.initialize(mockDefaultValue); +describeCompat( + "LiveFollowMode", + ( + getTestObjectProvider: ( + options?: ITestObjectProviderOptions + ) => ITestObjectProvider + ) => { + it("Should initialize with correct defaults", async () => { + const { object1, object2, dispose } = await getObjects( + getTestObjectProvider + ); + let init1 = object1.initialize(mockDefaultValue); + let init2 = object2.initialize(mockDefaultValue); - await Promise.all([init1, init2]); + await Promise.all([init1, init2]); - function assertDefaultValues() { - // state should be defined - assert( - object1.state !== undefined, - "object1.state should be defined" - ); - assert( - object2.state !== undefined, - "object2.state should be defined" - ); + function assertDefaultValues() { + // state should be defined + assert( + object1.state !== undefined, + "object1.state should be defined" + ); + assert( + object2.state !== undefined, + "object2.state should be defined" + ); - // local user should be defined - assert( - object1.localUser !== undefined, - "object1.localUser should be defined" - ); - assert( - object2.localUser !== undefined, - "object2.localUser should be defined" - ); + // local user should be defined + assert( + object1.localUser !== undefined, + "object1.localUser should be defined" + ); + assert( + object2.localUser !== undefined, + "object2.localUser should be defined" + ); - // local user should be following themselves to start - assert( - object1.state.followingUserId === object1.localUser.userId, - "object1 state should show followingUserId is equal to local user's id" - ); - assert( - object2.state.followingUserId === object2.localUser.userId, - "object2 state should show followingUserId is equal to local user's id" - ); + // local user should be following themselves to start + assert( + object1.state.followingUserId === object1.localUser.userId, + "object1 state should show followingUserId is equal to local user's id" + ); + assert( + object2.state.followingUserId === object2.localUser.userId, + "object2 state should show followingUserId is equal to local user's id" + ); - // state.type should be local + // state.type should be local + assert( + object1.state.type === FollowModeType.local, + `object1.state.type should be local, instead is ${object1.state.type}` + ); + assert( + object2.state.type === FollowModeType.local, + `object2.state.type should be local, instead is ${object2.state.type}` + ); + + // state.isLocalValue should be true + assert( + object1.state.isLocalValue === true, + `object1.state.isLocalValue should be true` + ); + assert( + object2.state.type === FollowModeType.local, + `object1.state.isLocalValue should be true` + ); + + // state.otherUsersCount should be 0 + assert( + object1.state.otherUsersCount === 0, + `object1.state.otherUsersCount should be 0, instead is ${object1.state.otherUsersCount}` + ); + assert( + object2.state.otherUsersCount === 0, + `object2.state.otherUsersCount should be 0, instead is ${object2.state.otherUsersCount}` + ); + + // state.value.page should be equal to mockDefaultValue.page + assert( + object1.state.value.page === mockDefaultValue.page, + `object1.state.value.page should be ${mockDefaultValue.page}, instead is ${object1.state.value.page}` + ); + assert( + object2.state.value.page === mockDefaultValue.page, + `object2.state.value.page should be ${mockDefaultValue.page}, instead is ${object2.state.value.page}` + ); + } + assertDefaultValues(); + + await waitForDelay(2); + // default values should remain unchanged once initial presence update is sent + assertDefaultValues(); + + const users1 = object1.getUsers(); + const users2 = object2.getUsers(); + const nonLocalUser1 = users1.find((u) => !u.isLocalUser); + const nonLocalUser2 = users2.find((u) => !u.isLocalUser); + + // users should have correct length assert( - object1.state.type === FollowModeType.local, - `object1.state.type should be local, instead is ${object1.state.type}` + users1.length === 2, + `users1.length should be 2, instead is ${users1.length}` ); assert( - object2.state.type === FollowModeType.local, - `object2.state.type should be local, instead is ${object2.state.type}` + users2.length === 2, + `users2.length should be 2, instead is ${users2.length}` ); - - // state.isLocalValue should be true + // users should contain non-local user assert( - object1.state.isLocalValue === true, - `object1.state.isLocalValue should be true` + nonLocalUser1 !== undefined, + "nonLocalUser1 should be defined" ); assert( - object2.state.type === FollowModeType.local, - `object1.state.isLocalValue should be true` + nonLocalUser2 !== undefined, + "nonLocalUser2 should be defined" ); - - // state.otherUsersCount should be 0 + // non-local user data should be defined assert( - object1.state.otherUsersCount === 0, - `object1.state.otherUsersCount should be 0, instead is ${object1.state.otherUsersCount}` + nonLocalUser1.data !== undefined, + "nonLocalUser1.data should be defined" ); assert( - object2.state.otherUsersCount === 0, - `object2.state.otherUsersCount should be 0, instead is ${object2.state.otherUsersCount}` + nonLocalUser2.data !== undefined, + "nonLocalUser2.data should be defined" ); - - // state.value.page should be equal to mockDefaultValue.page + // non-local user should have correct default values assert( - object1.state.value.page === mockDefaultValue.page, - `object1.state.value.page should be ${mockDefaultValue.page}, instead is ${object1.state.value.page}` + nonLocalUser1.data.stateValue.page === mockDefaultValue.page, + `nonLocalUser1.data.stateValue.page should be ${mockDefaultValue.page}, instead is ${nonLocalUser1.data.stateValue.page}` ); assert( - object2.state.value.page === mockDefaultValue.page, - `object2.state.value.page should be ${mockDefaultValue.page}, instead is ${object2.state.value.page}` + nonLocalUser2.data.stateValue.page === mockDefaultValue.page, + `nonLocalUser2.data.stateValue.page should be ${mockDefaultValue.page}, instead is ${nonLocalUser2.data.stateValue.page}` ); - } - assertDefaultValues(); - - await waitForDelay(60); - // default values should remain unchanged once initial presence update is sent - assertDefaultValues(); - const users1 = object1.getUsers(); - const users2 = object2.getUsers(); - const nonLocalUser1 = users1.find((u) => !u.isLocalUser); - const nonLocalUser2 = users2.find((u) => !u.isLocalUser); - - // users should have correct length - assert( - users1.length === 2, - `users1.length should be 2, instead is ${users1.length}` - ); - assert( - users2.length === 2, - `users2.length should be 2, instead is ${users2.length}` - ); - // users should contain non-local user - assert(nonLocalUser1 !== undefined, "nonLocalUser1 should be defined"); - assert(nonLocalUser2 !== undefined, "nonLocalUser2 should be defined"); - // non-local user data should be defined - assert( - nonLocalUser1.data !== undefined, - "nonLocalUser1.data should be defined" - ); - assert( - nonLocalUser2.data !== undefined, - "nonLocalUser2.data should be defined" - ); - // non-local user should have correct default values - assert( - nonLocalUser1.data.stateValue.page === mockDefaultValue.page, - `nonLocalUser1.data.stateValue.page should be ${mockDefaultValue.page}, instead is ${nonLocalUser1.data.stateValue.page}` - ); - assert( - nonLocalUser2.data.stateValue.page === mockDefaultValue.page, - `nonLocalUser2.data.stateValue.page should be ${mockDefaultValue.page}, instead is ${nonLocalUser2.data.stateValue.page}` - ); - - dispose(); - }); + dispose(); + }); - it("Should correctly broadcast local user's state value", async () => { - const { object1, object2, dispose } = await getObjects( - getTestObjectProvider - ); - let init1 = object1.initialize(mockDefaultValue); - let init2 = object2.initialize(mockDefaultValue); + it("Should correctly broadcast local user's state value", async () => { + const { object1, object2, dispose } = await getObjects( + getTestObjectProvider + ); + let init1 = object1.initialize(mockDefaultValue); + let init2 = object2.initialize(mockDefaultValue); - await Promise.all([init1, init2]); + await Promise.all([init1, init2]); - // allow remote presence to be received to make the test a bit cleaner - await waitForDelay(0); + // allow remote presence to be received to make the test a bit cleaner + await waitForDelay(0); - const user1StateValue = { - page: "bananas", - }; - const user2StateValue = { - page: "apples", - }; + const user1StateValue = { + page: "bananas", + }; + const user2StateValue = { + page: "apples", + }; - const object1StateDone = new Deferred(); - object1.on("stateChanged", (state, local) => { - assert( - local, - "object1: should not receive non-local stateChanged event" - ); - assert( - state.isLocalValue, - "object1: state should be isLocalValue true" - ); - assert( - state.type === FollowModeType.local, - "object1: state should be type of local" - ); - assert( - state.followingUserId === object1.localUser!.userId, - `object1: state should have followingUserId equal to local user, instead is ${state.followingUserId}` - ); - assert( - state.otherUsersCount === 0, - `object1: state should have otherUsersCount equal to 0, instead is ${state.otherUsersCount}` - ); - assert( - state.value.page === user1StateValue.page, - `object1: state should have value.page equal to ${user1StateValue.page}, instead is ${state.value.page}` - ); - object1StateDone.resolve(); - }); - const object1PresenceDone = new Deferred(); - let numPresence1Updates = 0; - object1.on("presenceChanged", (presence, local) => { - assert( - presence.data !== undefined, - "object1: presence.data should not be undefined" - ); - if (local) { + const object1StateDone = new Deferred(); + object1.on("stateChanged", (state, local) => { assert( - presence.data.stateValue.page === user1StateValue.page, - `object1: local presence should have data.page of ${user1StateValue.page}, instead is ${presence.data.stateValue.page}` + local, + "object1: should not receive non-local stateChanged event" ); - } else { assert( - presence.data.stateValue.page === user2StateValue.page, - `object1: non-local presence should have data.page of ${user2StateValue.page}, instead is ${presence.data.stateValue.page}` + state.isLocalValue, + "object1: state should be isLocalValue true" ); - } - numPresence1Updates += 1; - if (numPresence1Updates === 2) { - object1PresenceDone.resolve(); - } + assert( + state.type === FollowModeType.local, + "object1: state should be type of local" + ); + assert( + state.followingUserId === object1.localUser!.userId, + `object1: state should have followingUserId equal to local user, instead is ${state.followingUserId}` + ); + assert( + state.otherUsersCount === 0, + `object1: state should have otherUsersCount equal to 0, instead is ${state.otherUsersCount}` + ); + assert( + state.value.page === user1StateValue.page, + `object1: state should have value.page equal to ${user1StateValue.page}, instead is ${state.value.page}` + ); + object1StateDone.resolve(); + }); + const object1PresenceDone = new Deferred(); + let numPresence1Updates = 0; + object1.on("presenceChanged", (presence, local) => { + assert( + presence.data !== undefined, + "object1: presence.data should not be undefined" + ); + if (local) { + assert( + presence.data.stateValue.page === user1StateValue.page, + `object1: local presence should have data.page of ${user1StateValue.page}, instead is ${presence.data.stateValue.page}` + ); + } else { + assert( + presence.data.stateValue.page === user2StateValue.page, + `object1: non-local presence should have data.page of ${user2StateValue.page}, instead is ${presence.data.stateValue.page}` + ); + } + numPresence1Updates += 1; + if (numPresence1Updates === 2) { + object1PresenceDone.resolve(); + } + }); + + const object2StateDone = new Deferred(); + object2.on("stateChanged", (state, local) => { + assert( + local, + "object2: should not receive non-local stateChanged event" + ); + assert( + state.isLocalValue, + "object2: state should be isLocalValue true" + ); + assert( + state.type === FollowModeType.local, + "object2: state should be type of local" + ); + assert( + state.followingUserId === object2.localUser!.userId, + `object2: state should have followingUserId equal to local user, instead is ${state.followingUserId}` + ); + assert( + state.otherUsersCount === 0, + `object2: state should have otherUsersCount equal to 0, instead is ${state.otherUsersCount}` + ); + assert( + state.value.page === user2StateValue.page, + `object2: state should have value.page equal to ${user2StateValue.page}, instead is ${state.value.page}` + ); + object1StateDone.resolve(); + }); + const object2PresenceDone = new Deferred(); + let numPresence2Updates = 0; + object2.on("presenceChanged", (presence, local) => { + assert( + presence.data !== undefined, + "object2: presence.data should not be undefined" + ); + if (local) { + assert( + presence.data.stateValue.page === user2StateValue.page, + `object2: local presence should have data.page of ${user2StateValue.page}, instead is ${presence.data.stateValue.page}` + ); + } else { + assert( + presence.data.stateValue.page === user1StateValue.page, + `object2: non-local presence should have data.page of ${user1StateValue.page}, instead is ${presence.data.stateValue.page}` + ); + } + numPresence2Updates += 1; + if (numPresence2Updates === 2) { + object1PresenceDone.resolve(); + } + }); + + const update1 = object1.update(user1StateValue); + const update2 = object2.update(user2StateValue); + await Promise.all([update1, update2]); + await Promise.all([ + object1StateDone, + object1PresenceDone, + object2StateDone, + object2PresenceDone, + ]); + + dispose(); }); - const object2StateDone = new Deferred(); - object2.on("stateChanged", (state, local) => { - assert( - local, - "object2: should not receive non-local stateChanged event" - ); - assert( - state.isLocalValue, - "object2: state should be isLocalValue true" - ); - assert( - state.type === FollowModeType.local, - "object2: state should be type of local" - ); - assert( - state.followingUserId === object2.localUser!.userId, - `object2: state should have followingUserId equal to local user, instead is ${state.followingUserId}` + it("Should be able to start/stop presenting", async () => { + const { object1, object2, dispose } = await getObjects( + getTestObjectProvider ); - assert( - state.otherUsersCount === 0, - `object2: state should have otherUsersCount equal to 0, instead is ${state.otherUsersCount}` + const user1StateValue = { + page: "bananas", + }; + const user2StateValue = { + page: "apples", + }; + let init1 = object1.initialize(user1StateValue); + let init2 = object2.initialize(user2StateValue); + + await Promise.all([init1, init2]); + + // allow remote presence to be received to make the test a bit cleaner + await waitForDelay(0); + + // Validate that object1 can become the presenter + await validateStartPresenting(object1, object2); + // Validate that object2 can take over as the presenter + await validateStartPresenting(object2, object1); + + // object2 will now be in control, validate stopPresenting + await validateStopPresenting(object2, object1); + + dispose(); + }); + + it("Should be able to start/stop suspension from presenter", async () => { + const { object1, object2, dispose } = await getObjects( + getTestObjectProvider ); - assert( - state.value.page === user2StateValue.page, - `object2: state should have value.page equal to ${user2StateValue.page}, instead is ${state.value.page}` + const user1StateValue = { + page: "bananas", + }; + const user2StateValue = { + page: "apples", + }; + let init1 = object1.initialize(user1StateValue); + let init2 = object2.initialize(user2StateValue); + + await Promise.all([init1, init2]); + + // allow remote presence to be received to make the test a bit cleaner + await waitForDelay(0); + + // Validate that object1 can become the presenter + await validateStartPresenting(object1, object2); + + // Validate that object2 can suspend + await validateStartSuspensionPresenter(object1, object2); + // Validate that object2 can stop suspension + await validateEndSuspensionPresenter(object1, object2); + + dispose(); + }); + + it("Should be able to start/stop following", async () => { + const { object1, object2, dispose } = await getObjects( + getTestObjectProvider ); - object1StateDone.resolve(); + const user1StateValue = { + page: "bananas", + }; + const user2StateValue = { + page: "apples", + }; + let init1 = object1.initialize(user1StateValue); + let init2 = object2.initialize(user2StateValue); + + await Promise.all([init1, init2]); + + // allow remote presence to be received to make the test a bit cleaner + await waitForDelay(0); + + // Validate that object1 can follow object2 + await validateStartFollowing(object1, object2); + // Validate that object1 can stop following object2 + await validateStopFollowing(object1, object2); + // Validate that object2 can follow object1 + await validateStartFollowing(object2, object1); + // Validate that object2 can stop following object1 + await validateStopFollowing(object2, object1); + + dispose(); }); - const object2PresenceDone = new Deferred(); - let numPresence2Updates = 0; - object2.on("presenceChanged", (presence, local) => { - assert( - presence.data !== undefined, - "object2: presence.data should not be undefined" + + it("Should be able to start/end suspension while following", async () => { + const { object1, object2, dispose } = await getObjects( + getTestObjectProvider ); - if (local) { - assert( - presence.data.stateValue.page === user2StateValue.page, - `object2: local presence should have data.page of ${user2StateValue.page}, instead is ${presence.data.stateValue.page}` - ); - } else { - assert( - presence.data.stateValue.page === user1StateValue.page, - `object2: non-local presence should have data.page of ${user1StateValue.page}, instead is ${presence.data.stateValue.page}` - ); - } - numPresence2Updates += 1; - if (numPresence2Updates === 2) { - object1PresenceDone.resolve(); - } + const user1StateValue = { + page: "bananas", + }; + const user2StateValue = { + page: "apples", + }; + let init1 = object1.initialize(user1StateValue); + let init2 = object2.initialize(user2StateValue); + + await Promise.all([init1, init2]); + + // allow remote presence to be received to make the test a bit cleaner + await waitForDelay(0); + + // Validate that object1 can follow object2 + await validateStartFollowing(object1, object2); + // Validate that object1 can suspend from following object 2 + await validateStartSuspensionFollower(object1, object2); + // Validate that object1 can end suspension from following object 2 + await validateEndSuspensionFollower(object1, object2); + + dispose(); }); - const update1 = object1.update(user1StateValue); - const update2 = object2.update(user2StateValue); - await Promise.all([update1, update2]); - await Promise.all([ - object1StateDone, - object1PresenceDone, - object2StateDone, - object2PresenceDone, - ]); - - dispose(); - }); - - it("Should be able to start/stop presenting", async () => { - const { object1, object2, dispose } = await getObjects( - getTestObjectProvider - ); - const user1StateValue = { - page: "bananas", - }; - const user2StateValue = { - page: "apples", - }; - let init1 = object1.initialize(user1StateValue); - let init2 = object2.initialize(user2StateValue); - - await Promise.all([init1, init2]); - - // allow remote presence to be received to make the test a bit cleaner - await waitForDelay(0); - - // Validate that object1 can become the presenter - await validateStartPresenting(object1, object2); - // Validate that object2 can take over as the presenter - await validateStartPresenting(object2, object1); - - // object2 will now be in control, validate stopPresenting - await validateStopPresenting(object2, object1); - - dispose(); - }); - - it("Should be able to start/stop suspension from presenter", async () => { - const { object1, object2, dispose } = await getObjects( - getTestObjectProvider - ); - const user1StateValue = { - page: "bananas", - }; - const user2StateValue = { - page: "apples", - }; - let init1 = object1.initialize(user1StateValue); - let init2 = object2.initialize(user2StateValue); - - await Promise.all([init1, init2]); - - // allow remote presence to be received to make the test a bit cleaner - await waitForDelay(0); - - // Validate that object1 can become the presenter - await validateStartPresenting(object1, object2); - - // Validate that object2 can suspend - await validateStartSuspensionPresenter(object1, object2); - // Validate that object2 can stop suspension - await validateEndSuspensionPresenter(object1, object2); - - dispose(); - }); - - it("Should be able to start/stop following", async () => { - const { object1, object2, dispose } = await getObjects( - getTestObjectProvider - ); - const user1StateValue = { - page: "bananas", - }; - const user2StateValue = { - page: "apples", - }; - let init1 = object1.initialize(user1StateValue); - let init2 = object2.initialize(user2StateValue); - - await Promise.all([init1, init2]); - - // allow remote presence to be received to make the test a bit cleaner - await waitForDelay(0); - - // Validate that object1 can follow object2 - await validateStartFollowing(object1, object2); - // Validate that object1 can stop following object2 - await validateStopFollowing(object1, object2); - // Validate that object2 can follow object1 - await validateStartFollowing(object2, object1); - // Validate that object2 can stop following object1 - await validateStopFollowing(object2, object1); - - dispose(); - }); - - it("Should be able to start/end suspension while following", async () => { - const { object1, object2, dispose } = await getObjects( - getTestObjectProvider - ); - const user1StateValue = { - page: "bananas", - }; - const user2StateValue = { - page: "apples", - }; - let init1 = object1.initialize(user1StateValue); - let init2 = object2.initialize(user2StateValue); - - await Promise.all([init1, init2]); - - // allow remote presence to be received to make the test a bit cleaner - await waitForDelay(0); - - // Validate that object1 can follow object2 - await validateStartFollowing(object1, object2); - // Validate that object1 can suspend from following object 2 - await validateStartSuspensionFollower(object1, object2); - // Validate that object1 can end suspension from following object 2 - await validateEndSuspensionFollower(object1, object2); - - dispose(); - }); - - it("Presenting should override following specific user", async () => { - const { object1, object2, dispose } = await getObjects( - getTestObjectProvider - ); - const user1StateValue = { - page: "bananas", - }; - const user2StateValue = { - page: "apples", - }; - let init1 = object1.initialize(user1StateValue); - let init2 = object2.initialize(user2StateValue); - - await Promise.all([init1, init2]); - - // allow remote presence to be received to make the test a bit cleaner - await waitForDelay(0); - - // Validate that object1 can follow object2 - await validateStartFollowing(object1, object2); - // Validate that object1 can start presenting - await validateStartPresenting(object1, object2); - - dispose(); - }); -}); + it("Presenting should override following specific user", async () => { + const { object1, object2, dispose } = await getObjects( + getTestObjectProvider + ); + const user1StateValue = { + page: "bananas", + }; + const user2StateValue = { + page: "apples", + }; + let init1 = object1.initialize(user1StateValue); + let init2 = object2.initialize(user2StateValue); + + await Promise.all([init1, init2]); + + // allow remote presence to be received to make the test a bit cleaner + await waitForDelay(0); + + // Validate that object1 can follow object2 + await validateStartFollowing(object1, object2); + // Validate that object1 can start presenting + await validateStartPresenting(object1, object2); + + dispose(); + }); + } +); async function validateStartPresenting( objectToPresent: LiveFollowMode, diff --git a/packages/live-share/src/test/LivePresence.audience.spec.ts b/packages/live-share/src/test/LivePresence.audience.spec.ts new file mode 100644 index 000000000..9907566ed --- /dev/null +++ b/packages/live-share/src/test/LivePresence.audience.spec.ts @@ -0,0 +1,91 @@ +/*! + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Microsoft Live Share SDK License. + */ + +import { strict as assert } from "assert"; +import { TestLiveShareHost } from "../TestLiveShareHost.js"; +import { LiveShareClient } from "../LiveShareClient.js"; +import { LivePresence } from "../LivePresence.js"; +import { PresenceStatus } from "../LivePresenceUser.js"; +import { waitForDelay } from "../internals/utils.js"; +import { InsecureTokenProvider } from "@fluidframework/test-runtime-utils/internal"; + +describe("LivePresence Fluid Audience tests", () => { + let containerId: string | undefined; + const getContainerId = (): string | undefined => { + return containerId; + }; + const setContainerId = (newContainerId: string) => { + containerId = newContainerId; + }; + const host = TestLiveShareHost.create( + new InsecureTokenProvider("", { + id: "testId", + name: "Test User", + }), + getContainerId, + setContainerId + ); + let client1: LiveShareClient; + let client2: LiveShareClient; + + const testPresenceKey = "TEST-MAP-KEY"; + + beforeEach(async () => { + client1 = new LiveShareClient(host); + client2 = new LiveShareClient(host); + containerId = undefined; + await client1.join(); + await client2.join(); + }); + + it("LivePresence User should go offline when Audience member is removed", async () => { + const promise1 = client1.getDDS( + testPresenceKey, + LivePresence, + (dds: LivePresence) => { + assert( + dds !== undefined, + "dds is not defined in onFirstInitialize callback" + ); + } + ); + const promise2 = client2.getDDS( + testPresenceKey, + LivePresence, + (dds: LivePresence) => { + assert( + dds !== undefined, + "dds is not defined in onFirstInitialize callback" + ); + } + ); + + // Wait for dds to to be created + const [dds1, dds2] = await Promise.all([promise1, promise2]); + + await dds1.initialize(undefined); + await dds2.initialize(undefined); + + client1.results?.container.disconnect(); + + await waitForDelay(10); + + const onlineFromObject2Perpsective = dds2 + .getUsers() + .filter((u) => u.status == PresenceStatus.online).length; + const offlineFromObject2Perpsective = dds2 + .getUsers() + .filter((u) => u.status == PresenceStatus.offline).length; + + assert( + onlineFromObject2Perpsective === 1, + `should have 1 online user, is actually: ${onlineFromObject2Perpsective}` + ); + assert( + offlineFromObject2Perpsective === 1, + `should have 1 offline user, is actually: ${offlineFromObject2Perpsective}` + ); + }); +}); diff --git a/packages/live-share/src/test/LivePresence.spec.ts b/packages/live-share/src/test/LivePresence.spec.ts index a792296bb..03f85b2ff 100644 --- a/packages/live-share/src/test/LivePresence.spec.ts +++ b/packages/live-share/src/test/LivePresence.spec.ts @@ -4,13 +4,15 @@ */ import { strict as assert } from "assert"; -import { requestFluidObject } from "@fluidframework/runtime-utils"; -import { ITestObjectProvider } from "@fluidframework/test-utils"; -import { describeNoCompat } from "@fluidframework/test-version-utils"; -import { LivePresence } from "../LivePresence"; -import { PresenceState } from "../LivePresenceUser"; -import { waitForDelay } from "../internals"; -import { Deferred } from "../internals"; +import { + ITestObjectProvider, + fluidEntryPoint, + getContainerEntryPointBackCompat, +} from "@fluidframework/test-utils/internal"; +import { LivePresenceClass } from "../LivePresence.js"; +import { PresenceStatus } from "../LivePresenceUser.js"; +import { waitForDelay } from "../internals/utils.js"; +import { Deferred } from "../internals/Deferred.js"; import { IClientInfo, IFluidContainerInfo, @@ -18,21 +20,40 @@ import { ILiveShareHost, INtpTimeInfo, UserMeetingRole, -} from "../interfaces"; -import { TestLiveShareHost } from "../TestLiveShareHost"; -import { getLiveDataObjectClass } from "../schema-injection-utils"; -import { MockLiveShareRuntime } from "./MockLiveShareRuntime"; - -class TestLivePresence< - TData extends object = object -> extends LivePresence { +} from "../interfaces.js"; +import { TestLiveShareHost } from "../TestLiveShareHost.js"; +import { getLiveDataObjectKind } from "../internals/schema-injection-utils.js"; +import { + MockLiveShareRuntime, + MockTokenProvider, +} from "../internals/mock/MockLiveShareRuntime.js"; +import { + describeCompat, + ITestObjectProviderOptions, +} from "@live-share-private/test-utils"; +import { SharedObjectKind } from "fluid-framework"; + +class TestLivePresenceClass< + TData extends object | undefined | null = object, +> extends LivePresenceClass { public async clientId(): Promise { return await this.waitUntilConnected(); } } +export type TestLivePresence = + TestLivePresenceClass; + +// eslint-disable-next-line no-redeclare +export const TestLivePresence = (() => { + const kind = TestLivePresenceClass; + return kind as typeof kind & SharedObjectKind>; +})(); + async function getObjects( - getTestObjectProvider, + getTestObjectProvider: ( + options?: ITestObjectProviderOptions + ) => ITestObjectProvider, updateInterval: number = 10000, object2canSendBackgroundUpdates = true, customHost?: ILiveShareHost @@ -46,11 +67,11 @@ async function getObjects( } liveRuntime2.canSendBackgroundUpdates = object2canSendBackgroundUpdates; - let ObjectProxy1: any = getLiveDataObjectClass< - TestLivePresence<{ foo: string }> + let ObjectProxy1: any = getLiveDataObjectKind< + TestLivePresence<{ foo: string } | undefined> >(TestLivePresence, liveRuntime1); - let ObjectProxy2: any = getLiveDataObjectClass< - TestLivePresence<{ foo: string }> + let ObjectProxy2: any = getLiveDataObjectKind< + TestLivePresence<{ foo: string } | undefined> >(TestLivePresence, liveRuntime2); await liveRuntime1.start(); @@ -58,17 +79,21 @@ async function getObjects( let provider: ITestObjectProvider = getTestObjectProvider(); - let container1 = await provider.createContainer(ObjectProxy1.factory); - let object1 = await requestFluidObject>( - container1, - "default" + let container1 = await provider.createContainer( + ObjectProxy1.factory as fluidEntryPoint ); + let object1 = + await getContainerEntryPointBackCompat< + TestLivePresence<{ foo: string } | undefined> + >(container1); - let container2 = await provider.loadContainer(ObjectProxy2.factory); - let object2 = await requestFluidObject>( - container2, - "default" + let container2 = await provider.loadContainer( + ObjectProxy2.factory as fluidEntryPoint ); + let object2 = + await getContainerEntryPointBackCompat< + TestLivePresence<{ foo: string } | undefined> + >(container2); // need to be connected to send signals if (!container1.connect) { await new Promise((resolve) => container1.once("connected", resolve)); @@ -104,857 +129,818 @@ async function getObjects( }; } -describeNoCompat("LivePresence", (getTestObjectProvider) => { - it("Should exchange initial presence information", async () => { - const { object1, object2, disposeAll } = await getObjects( - getTestObjectProvider - ); - const object1done = new Deferred(); - object1.on("presenceChanged", (user, local) => { - try { - if (!local) { - assert(user != null, `user2: Null user arg`); - assert( - user.state == PresenceState.online, - `user2: Unexpected presence state of ${user.state}` - ); - assert( - user.data == undefined, - `user2: Unexpected data object of ${user.data}` - ); - object1done.resolve(); +describeCompat( + "LivePresence", + ( + getTestObjectProvider: ( + options?: ITestObjectProviderOptions + ) => ITestObjectProvider + ) => { + it("Should exchange initial presence information", async () => { + const { object1, object2, disposeAll } = await getObjects( + getTestObjectProvider + ); + const object1done = new Deferred(); + object1.on("presenceChanged", (user, local) => { + try { + if (!local) { + assert(user != null, `user2: Null user arg`); + assert( + user.status == PresenceStatus.online, + `user2: Unexpected presence state of ${user.status}` + ); + assert( + user.data == undefined, + `user2: Unexpected data object of ${user.data}` + ); + object1done.resolve(); + } + } catch (err) { + object1done.reject(err); } - } catch (err) { - object1done.reject(err); - } - }); + }); - assert(!object1.isInitialized, `presence already initialized`); - await object1.initialize(); - assert(object1.isInitialized, `presence not initialized`); + assert(!object1.isInitialized, `presence already initialized`); + await object1.initialize(undefined); + assert(object1.isInitialized, `presence not initialized`); - const object2done = new Deferred(); - object2.on("presenceChanged", (user, local) => { - try { - if (!local) { - assert(user != null, `user1: Null user arg`); - assert( - user.state == PresenceState.online, - `user1: Unexpected presence state of ${user.state}` - ); - assert( - user.data == undefined, - `user1: Unexpected data object of ${user.data}` - ); - object2done.resolve(); + const object2done = new Deferred(); + object2.on("presenceChanged", (user, local) => { + try { + if (!local) { + assert(user != null, `user1: Null user arg`); + assert( + user.status == PresenceStatus.online, + `user1: Unexpected presence state of ${user.status}` + ); + assert( + user.data == undefined, + `user1: Unexpected data object of ${user.data}` + ); + object2done.resolve(); + } + } catch (err) { + object2done.reject(err); } - } catch (err) { - object2done.reject(err); - } + }); + await object2.initialize(undefined); + + // Wait for events to trigger + await Promise.all([object1done.promise, object2done.promise]); + + disposeAll(); }); - await object2.initialize(); - // Wait for events to trigger - await Promise.all([object1done.promise, object2done.promise]); + it("test canSendBackgroundUpdates only sends when true", async () => { + const canSendBackgroundUpdatesObject2 = false; + const { object1, object2, disposeAll } = await getObjects( + getTestObjectProvider, + 10000, + canSendBackgroundUpdatesObject2 + ); + const object2done = new Deferred(); - disposeAll(); - }); + await object1.initialize(undefined); - it("Should start in alternate state", async () => { - const { object1, object2, disposeAll } = await getObjects( - getTestObjectProvider - ); - const object1done = new Deferred(); - object1.on("presenceChanged", (user, local) => { - try { - if (local) { - assert( - user.state == PresenceState.away, - `user1: Unexpected presence state of ${user.state}` - ); - assert( - user.data == undefined, - `user1: Unexpected data object of ${user.data}` - ); - object1done.resolve(); - } - } catch (err) { - object1done.reject(err); - } - }); - await object1.initialize(undefined, PresenceState.away); + let object2PresenceChangeTotalCount: number = 0; - const object2done = new Deferred(); - object2.on("presenceChanged", (user, local) => { - try { + let object2FromObject2PerspectivePresenceChangeCount: number = 0; + object2.on("presenceChanged", (user, local) => { if (local) { - assert( - user.state == PresenceState.offline, - `user2: Unexpected presence state of ${user.state}` - ); - assert( - user.data == undefined, - `user2: Unexpected data object of ${user.data}` - ); + object2FromObject2PerspectivePresenceChangeCount += 1; + object2PresenceChangeTotalCount += 1; object2done.resolve(); } - } catch (err) { - object2done.reject(err); - } - }); - await object2.initialize(undefined, PresenceState.offline); - - // Wait for events to trigger - await Promise.all([object1done.promise, object2done.promise]); - - disposeAll(); - }); - - it("test canSendBackgroundUpdates only sends when true", async () => { - const canSendBackgroundUpdatesObject2 = false; - const { object1, object2, disposeAll } = await getObjects( - getTestObjectProvider, - 10000, - canSendBackgroundUpdatesObject2 - ); - const object2done = new Deferred(); - - await object1.initialize(undefined); - - let object2PresenceChangeCount: number = 0; - let object2PresenceChangeOnlineCount: number = 0; - let object2PresenceChangeOfflineCount: number = 0; - object2.on("presenceChanged", (user, local) => { - if (local) { - object2PresenceChangeCount += 1; - if (user.state === "online") { - object2PresenceChangeOnlineCount += 1; - } else { - object2PresenceChangeOfflineCount += 1; - } - object2done.resolve(); - } - }); - object1.on("presenceChanged", (user, local) => { - if (!local) { - object2PresenceChangeCount += 1; - if (user.state === "online") { - object2PresenceChangeOnlineCount += 1; - } else { - object2PresenceChangeOfflineCount += 1; - } - } - }); - await object2.initialize(undefined); - - // as any to access private updateInternal, set background to true - // should not cause an event to be sent - const backgroundUpdate1 = true; - (object2 as any).updateInternal( - "hello", - object2.localUser?.state, - false, - backgroundUpdate1 - ); - - await waitForDelay(1); - // Wait for events to trigger - await object2done.promise; - assert( - object2PresenceChangeCount == 2, - `expected three events from object2, ${object2PresenceChangeCount}` - ); - assert( - object2PresenceChangeOnlineCount == 2, - `expected two events from object2 that was online, ${object2PresenceChangeOnlineCount}` - ); - assert( - object2PresenceChangeOfflineCount == 0, - `expected zero events from object2 that was offline, ${object2PresenceChangeOfflineCount}` - ); - assert( - object1.localUser !== undefined, - "local user should not be undefined" - ); - assert( - object2.localUser !== undefined, - "local user should not be undefined" - ); - - // should update as not a background update - const backgroundUpdateFalse = false; - (object2 as any).updateInternal( - "hello", - "offline", - false, - backgroundUpdateFalse - ); - await waitForDelay(1); - - assert( - object2PresenceChangeCount == 4, - `expected 4 events from object2, ${object2PresenceChangeCount}` - ); - assert( - object2PresenceChangeOnlineCount == 2, - `expected two events from object2 that was online, ${object2PresenceChangeOnlineCount}` - ); - assert( - object2PresenceChangeOfflineCount == 2, - `expected two events from object2 that was offline, ${object2PresenceChangeOfflineCount}` - ); - - disposeAll(); - }); - - it("Should start with initial data", async () => { - const { object1, object2, disposeAll } = await getObjects( - getTestObjectProvider - ); - const object1done = new Deferred(); - object1.on("presenceChanged", (user, local) => { - try { - if (!local) { - assert(user.data, `user2: NULL data`); - assert( - user.data.foo == "bar", - `user1: Unexpected data object of ${user.data}` - ); - object1done.resolve(); - } - } catch (err) { - object1done.reject(err); - } - }); - await object1.initialize({ foo: "bar" }, PresenceState.away); - assert(object1.localUser?.state == PresenceState.away); - assert(object1.localUser?.data?.foo == "bar"); + }); - const object2done = new Deferred(); - object2.on("presenceChanged", (user, local) => { - try { + let object1FromObject2PerspectivePresenceChangeCount: number = 0; + object1.on("presenceChanged", (user, local) => { if (!local) { - assert(user.data, `user1: NULL data`); - assert( - user.data.foo == "bar", - `user1: Unexpected data object of ${user.data}` - ); - object2done.resolve(); + object1FromObject2PerspectivePresenceChangeCount += 1; + object2PresenceChangeTotalCount += 1; } - } catch (err) { - object2done.reject(err); - } + }); + await object2.initialize(undefined); + + // as any to access private updateInternal, set background to true + // should not cause an event to be sent + const backgroundUpdate = true; + (object2 as any).updateInternal("hello", false, backgroundUpdate); + + await waitForDelay(1); + // Wait for events to trigger + await object2done.promise; + + assert( + object2FromObject2PerspectivePresenceChangeCount == 2, + `expected two events from object2 from perspective of object 2, ${object2FromObject2PerspectivePresenceChangeCount}` + ); + assert( + object1FromObject2PerspectivePresenceChangeCount == 1, + `expected one events from object2 from perspective of object 1, ${object1FromObject2PerspectivePresenceChangeCount}` + ); + + assert( + object1.localUser !== undefined, + "local user should not be undefined" + ); + assert( + object2.localUser !== undefined, + "local user should not be undefined" + ); + // should update as not a background update + const backgroundUpdateFalse = false; + (object2 as any).updateInternal( + "hello there", + false, + backgroundUpdateFalse + ); + await waitForDelay(1); + + assert( + // @ts-ignore invalid, assersion earlier in test is making the linter think this assertion is unintentional. + object2FromObject2PerspectivePresenceChangeCount == 3, + `expected 1 more event (3 total) from object2 from perspective of object 2, ${object2FromObject2PerspectivePresenceChangeCount}` + ); + assert( + // @ts-ignore invalid, assersion earlier in test is making the linter think this assertion is unintentional. + object1FromObject2PerspectivePresenceChangeCount == 2, + `expected 1 more event (2 total) from object2 from perspective of object 1, ${object1FromObject2PerspectivePresenceChangeCount}` + ); + assert( + object2PresenceChangeTotalCount == 5, + `expected five events from object2 that was online, ${object2PresenceChangeTotalCount}` + ); + + disposeAll(); }); - await object2.initialize({ foo: "bar" }, PresenceState.offline); - - // Wait for events to trigger - await Promise.all([object1done.promise, object2done.promise]); - - disposeAll(); - }); - - it("Should update() user presence", async () => { - const { object1, object2, disposeAll } = await getObjects( - getTestObjectProvider - ); - let triggered = false; - const object1done = new Deferred(); - object1.on("presenceChanged", (user, local) => { - try { - if (!local) { - if (triggered) { - assert(user.data, `user1: NULL data`); + + it("Should start with initial data", async () => { + const { object1, object2, disposeAll } = await getObjects( + getTestObjectProvider + ); + const object1done = new Deferred(); + object1.on("presenceChanged", (user, local) => { + try { + if (!local) { + assert(user.data, `user2: NULL data`); assert( user.data.foo == "bar", `user1: Unexpected data object of ${user.data}` ); - assert(user.state == PresenceState.offline); object1done.resolve(); - } else { - triggered = true; + } + } catch (err) { + object1done.reject(err); + } + }); + await object1.initialize({ foo: "bar" }); + assert(object1.localUser?.status == PresenceStatus.online); + assert(object1.localUser?.data?.foo == "bar"); + + const object2done = new Deferred(); + object2.on("presenceChanged", (user, local) => { + try { + if (!local) { + assert(user.data, `user1: NULL data`); assert( - !user.data, - `user1: data object passed when it shouldn't be` + user.data.foo == "bar", + `user1: Unexpected data object of ${user.data}` ); - assert(user.state == PresenceState.online); + object2done.resolve(); } + } catch (err) { + object2done.reject(err); } - } catch (err) { - object1done.reject(err); - } - }); - await object1.initialize(); + }); + await object2.initialize({ foo: "bar" }); - const object2Ready = new Deferred(); - object2.on("presenceChanged", (user, local) => { - object2Ready.resolve(); - }); - await object2.initialize(); - - // Wait for everything to start - await object2Ready.promise; - - // Update presence - object2.update({ foo: "bar" }, PresenceState.offline); - - // Wait for finish - await object1done.promise; - - disposeAll(); - }); - - it("Should enumerate users with forEach()", async () => { - const { object1, object2, disposeAll } = await getObjects( - getTestObjectProvider - ); - const ready = new Deferred(); - let object1UserId = ""; - let object2UserId = ""; - object1.on("presenceChanged", (user, local) => { - if (local) { - object1UserId = user.userId; - } else { - object2UserId = user.userId; - } - if (object1UserId && object2UserId) { - ready.resolve(); - } - }); - await object1.initialize(); - await object2.initialize(undefined, PresenceState.away); - - // Wait for ready and perform test - let user1Found = false; - let user2Found = false; - await ready.promise; - object1.getUsers().forEach((user) => { - switch (user.userId) { - case object1UserId: - user1Found = true; - break; - case object2UserId: - user2Found = true; - break; - } - }); + // Wait for events to trigger + await Promise.all([object1done.promise, object2done.promise]); - assert(user1Found && user2Found); - - disposeAll(); - }); - - it("Should filter users by state using forEach()", async () => { - const { object1, object2, disposeAll } = await getObjects( - getTestObjectProvider - ); - const ready = new Deferred(); - let object1UserId = ""; - let object2UserId = ""; - object1.on("presenceChanged", (user, local) => { - if (local) { - object1UserId = user.userId; - } else { - object2UserId = user.userId; - } - if (object1UserId && object2UserId) { - ready.resolve(); - } - }); - await object1.initialize(); - await object2.initialize(undefined, PresenceState.away); - - // Wait for ready and perform test - let user1Found = false; - let user2Found = false; - await ready.promise; - object1.getUsers(PresenceState.online).forEach((user) => { - switch (user.userId) { - case object1UserId: - user1Found = true; - break; - case object2UserId: - user2Found = true; - break; - } + disposeAll(); }); - assert(user1Found && !user2Found); + it("Should update() user presence", async () => { + const { object1, object2, disposeAll } = await getObjects( + getTestObjectProvider + ); + let triggered = false; + const object1done = new Deferred(); + object1.on("presenceChanged", (user, local) => { + try { + if (!local) { + if (triggered) { + assert(user.data, `user1: NULL data`); + assert( + user.data.foo == "bar", + `user1: Unexpected data object of ${user.data}` + ); + assert(user.status == PresenceStatus.online); + object1done.resolve(); + } else { + triggered = true; + assert( + !user.data, + `user1: data object passed when it shouldn't be` + ); + assert(user.status == PresenceStatus.online); + } + } + } catch (err) { + object1done.reject(err); + } + }); + await object1.initialize(undefined); + + const object2Ready = new Deferred(); + object2.on("presenceChanged", (user, local) => { + object2Ready.resolve(); + }); + await object2.initialize(undefined); + + // Wait for everything to start + await object2Ready.promise; - disposeAll(); - }); + // Update presence + object2.update({ foo: "bar" }); - it("Should return members using getUsers()", async () => { - const { object1, object2, disposeAll } = await getObjects( - getTestObjectProvider - ); - const ready = new Deferred(); - object1.on("presenceChanged", (user, local) => { - if (!local) { - ready.resolve(); - } + // Wait for finish + await object1done.promise; + + disposeAll(); }); - await object1.initialize(); - assert( - object1.getUsers().length === 1, - "getUsers() should not start empty" - ); - await object2.initialize(undefined, PresenceState.away); - - // Wait for ready and perform test - await ready.promise; - const users = object1.getUsers(); - - assert(Array.isArray(users), `getUsers() didn't return an array`); - assert(users.length == 2, `Array has a length of ${users.length}`); - - disposeAll(); - }); - - it("Should getCount() of the number of users being tracked", async () => { - const { object1, object2, disposeAll } = await getObjects( - getTestObjectProvider - ); - const ready = new Deferred(); - object1.on("presenceChanged", (user, local) => { - if (!local) { - ready.resolve(); - } + + it("Should enumerate users with forEach()", async () => { + const { object1, object2, disposeAll } = await getObjects( + getTestObjectProvider + ); + const ready = new Deferred(); + let object1UserId = ""; + let object2UserId = ""; + object1.on("presenceChanged", (user, local) => { + if (local) { + object1UserId = user.userId; + } else { + object2UserId = user.userId; + } + if (object1UserId && object2UserId) { + ready.resolve(); + } + }); + await object1.initialize(undefined); + await object2.initialize(undefined); + + // Wait for ready and perform test + let user1Found = false; + let user2Found = false; + await ready.promise; + object1.getUsers().forEach((user) => { + switch (user.userId) { + case object1UserId: + user1Found = true; + break; + case object2UserId: + user2Found = true; + break; + } + }); + + assert(user1Found && user2Found); + + disposeAll(); }); - await object1.initialize(); - await object2.initialize(undefined, PresenceState.away); - - // Wait for ready and perform test - await ready.promise; - const cnt = object1.getUsers().length; - - assert(cnt == 2); - - disposeAll(); - }); - - it("Should filter getCount()", async () => { - const { object1, object2, disposeAll } = await getObjects( - getTestObjectProvider - ); - const ready = new Deferred(); - object1.on("presenceChanged", (user, local) => { - if (!local) { - ready.resolve(); - } + + it("Should filter users by state and iterate using forEach()", async () => { + const { object1, object2, disposeAll } = await getObjects( + getTestObjectProvider + ); + const ready = new Deferred(); + let object1UserId = ""; + let object2UserId = ""; + object1.on("presenceChanged", (user, local) => { + if (local) { + object1UserId = user.userId; + } else { + object2UserId = user.userId; + } + if (object1UserId && object2UserId) { + ready.resolve(); + } + }); + await object1.initialize(undefined); + await object2.initialize(undefined); + + // Wait for ready and perform test + let user1Found = false; + let user2Found = false; + await ready.promise; + object1.getUsers(PresenceStatus.online).forEach((user) => { + switch (user.userId) { + case object1UserId: + user1Found = true; + break; + case object2UserId: + user2Found = true; + break; + } + }); + + assert(user1Found && user2Found); + + disposeAll(); }); - await object1.initialize(); - await object2.initialize(undefined, PresenceState.away); - - // Wait for ready and perform test - await ready.promise; - const cnt = object1.getUsers(PresenceState.away).length; - - assert(cnt == 1); - - disposeAll(); - }); - - it("Should getUser()", async () => { - const { object1, object2, disposeAll } = await getObjects( - getTestObjectProvider - ); - const ready = new Deferred(); - let object1UserId = ""; - let object2UserId = ""; - object1.on("presenceChanged", (user, local) => { - if (local) { - object1UserId = user.userId; - } else { - object2UserId = user.userId; - ready.resolve(); - } + + it("Should return members using getUsers()", async () => { + const { object1, object2, disposeAll } = await getObjects( + getTestObjectProvider + ); + const ready = new Deferred(); + object1.on("presenceChanged", (user, local) => { + if (!local) { + ready.resolve(); + } + }); + await object1.initialize(undefined); + assert( + object1.getUsers().length === 1, + "getUsers() should not start empty" + ); + await object2.initialize(undefined); + + // Wait for ready and perform test + await ready.promise; + const users = object1.getUsers(); + + assert(Array.isArray(users), `getUsers() didn't return an array`); + assert(users.length == 2, `Array has a length of ${users.length}`); + + disposeAll(); }); - await object1.initialize(); - await object2.initialize(undefined, PresenceState.away); - - // Wait for ready and perform test - await ready.promise; - const user1 = object1.getUser(object1UserId); - const user2 = object1.getUser(object2UserId); - - assert( - user1 && user1.userId == object1UserId, - `user1: missing or wrong user returned` - ); - assert(user1.isLocalUser, `user1: not local user`); - assert( - user2 && user2.userId == object2UserId, - `user2: missing or wrong user returned` - ); - assert(!user2.isLocalUser, `user2: is local user`); - - disposeAll(); - }); - - it("Should getPresenceForClient()", async () => { - const { object1, object2, disposeAll } = await getObjects( - getTestObjectProvider - ); - const ready = new Deferred(); - let object1UserId = ""; - let object1ClientId = ""; - let object2UserId = ""; - let object2ClientId = ""; - object1.on("presenceChanged", (user, local, clientId) => { - if (local) { - object1UserId = user.userId; - object1ClientId = clientId; - } else { - object2UserId = user.userId; - object2ClientId = clientId; - } - if (object1UserId && object2UserId) { - ready.resolve(); - } + + it("Should getCount() of the number of users being tracked", async () => { + const { object1, object2, disposeAll } = await getObjects( + getTestObjectProvider + ); + const ready = new Deferred(); + object1.on("presenceChanged", (user, local) => { + if (!local) { + ready.resolve(); + } + }); + await object1.initialize(undefined); + await object2.initialize(undefined); + + // Wait for ready and perform test + await ready.promise; + const cnt = object1.getUsers().length; + + assert(cnt == 2); + + disposeAll(); }); - await object1.initialize(); - await object2.initialize(undefined, PresenceState.away); - - // Wait for ready and get client ID's - await ready.promise; - - assert(await object1.clientId(), "object1.clientId is undefined"); - assert(await object2.clientId(), "object2.clientId is undefined"); - assert( - (await object1.clientId()) !== (await object2.clientId()), - "objects should not have the same clientId" - ); - - const users = object1.getUsers(); - assert( - users.length === 2, - "expected to have exactly 2 users in member list" - ); - assert( - users.filter((user) => user.userId === users[0].userId).length === - 1, - "should not have any duplicate user ids" - ); - - const user1 = object1.getUserForClient(object1ClientId); - assert(!!user1, "user1 is not known"); - assert( - user1.getConnections().length === 1, - "user1 connection count is not 1" - ); - const user2 = object1.getUserForClient(object2ClientId); - assert(!!user2, "user2 is not known"); - assert( - user2.getConnections().length === 1, - "user2 connection count is not 1" - ); - - assert( - user1.userId === object1UserId, - `user1: missing or wrong user returned, ${user1.userId} !== ${object1UserId}` - ); - assert(user1.isLocalUser, `user1: not local user`); - assert( - user2.userId === object2UserId, - `user2: missing or wrong user returned, ${user2.userId} !== ${object2UserId}` - ); - assert(!user2.isLocalUser, `user2: is local user`); - - disposeAll(); - }); - - it("Should send periodic presence updates", async () => { - const { object1, object2, disposeAll } = await getObjects( - getTestObjectProvider, - 20 - ); - const ready = new Deferred(); - object1.on("presenceChanged", (user, local) => { - if (!local) { - ready.resolve(); - } + + it("Should filter getCount()", async () => { + const { object1, object2, disposeAll } = await getObjects( + getTestObjectProvider + ); + const ready = new Deferred(); + object1.on("presenceChanged", (user, local) => { + if (!local) { + ready.resolve(); + } + }); + await object1.initialize(undefined); + await object2.initialize(undefined); + + // Wait for ready and perform test + await ready.promise; + assert(object1.getUsers(PresenceStatus.online).length == 2); + assert(object1.getUsers(PresenceStatus.away).length == 0); + assert(object1.getUsers(PresenceStatus.offline).length == 0); + + disposeAll(); }); - object1.expirationPeriod = 0.2; - await object1.initialize(); - object2.expirationPeriod = 0.2; - await object2.initialize(); + it("Should getUser()", async () => { + const { object1, object2, disposeAll } = await getObjects( + getTestObjectProvider + ); + const ready = new Deferred(); + let object1UserId = ""; + let object2UserId = ""; + object1.on("presenceChanged", (user, local) => { + if (local) { + object1UserId = user.userId; + } else { + object2UserId = user.userId; + ready.resolve(); + } + }); + await object1.initialize(undefined); + await object2.initialize(undefined); - // Wait for ready and then delay - await ready.promise; - await waitForDelay(600); + // Wait for ready and perform test + await ready.promise; + const user1 = object1.getUser(object1UserId); + const user2 = object1.getUser(object2UserId); - // Delay for a few updates - let count = 0; - object1.getUsers().forEach((user) => { - count++; assert( - user.state == PresenceState.online, - `user[${user.userId}] is ${user.state}` + user1 && user1.userId == object1UserId, + `user1: missing or wrong user returned` + ); + assert(user1.isLocalUser, `user1: not local user`); + assert( + user2 && user2.userId == object2UserId, + `user2: missing or wrong user returned` ); + assert(!user2.isLocalUser, `user2: is local user`); + + disposeAll(); }); - assert(count == 2, `Wrong number of users`); - - disposeAll(); - }); - - it("isLocalUser should be true for both clients with same userId and contain both clientIds", async () => { - // set same user test host - const mockHost = new SameUserLiveShareTestHost(); - const { object1, object2, disposeAll } = await getObjects( - getTestObjectProvider, - 10000, - true, - mockHost - ); - - const object1done = new Deferred(); - object1.on("presenceChanged", async (user, local) => { - try { - assert(user != null, `user1: Null user arg`); - assert( - user.state == PresenceState.online, - `user1: Unexpected presence state of ${user.state}` - ); - assert( - user.data == undefined, - `user1: Unexpected data object of ${user.data}` - ); - // If not local, we expect that isLocalUser will become true once we receive a message from the other client - if (!local && !user.isLocalUser) { - await waitForDelay(50); + it("Should getPresenceForClient()", async () => { + const { object1, object2, disposeAll } = await getObjects( + getTestObjectProvider + ); + const ready = new Deferred(); + let object1UserId = ""; + let object1ClientId = ""; + let object2UserId = ""; + let object2ClientId = ""; + object1.on("presenceChanged", (user, local, clientId) => { + if (local) { + object1UserId = user.userId; + object1ClientId = clientId; + } else { + object2UserId = user.userId; + object2ClientId = clientId; + } + if (object1UserId && object2UserId) { + ready.resolve(); } - assert(user.isLocalUser == true, `user1: should be local`); - object1done.resolve(); - } catch (err) { - object1done.reject(err); - } + }); + await object1.initialize(undefined); + await object2.initialize(undefined); + + // Wait for ready and get client ID's + await ready.promise; + + assert(await object1.clientId(), "object1.clientId is undefined"); + assert(await object2.clientId(), "object2.clientId is undefined"); + assert( + (await object1.clientId()) !== (await object2.clientId()), + "objects should not have the same clientId" + ); + + const users = object1.getUsers(); + assert( + users.length === 2, + "expected to have exactly 2 users in member list" + ); + assert( + users.filter((user) => user.userId === users[0].userId) + .length === 1, + "should not have any duplicate user ids" + ); + + const user1 = object1.getUserForClient(object1ClientId); + assert(!!user1, "user1 is not known"); + assert( + user1.getConnections().length === 1, + "user1 connection count is not 1" + ); + const user2 = object1.getUserForClient(object2ClientId); + assert(!!user2, "user2 is not known"); + assert( + user2.getConnections().length === 1, + "user2 connection count is not 1" + ); + + assert( + user1.userId === object1UserId, + `user1: missing or wrong user returned, ${user1.userId} !== ${object1UserId}` + ); + assert(user1.isLocalUser, `user1: not local user`); + assert( + user2.userId === object2UserId, + `user2: missing or wrong user returned, ${user2.userId} !== ${object2UserId}` + ); + assert(!user2.isLocalUser, `user2: is local user`); + + disposeAll(); }); - const object2done = new Deferred(); - object2.on("presenceChanged", async (user, local) => { - try { - assert(user != null, `user1: Null user arg`); - assert( - user.state == PresenceState.online, - `user1: Unexpected presence state of ${user.state}` - ); + it("Should send periodic presence updates", async () => { + const { object1, object2, disposeAll } = await getObjects( + getTestObjectProvider, + 20 + ); + const ready = new Deferred(); + object1.on("presenceChanged", (user, local) => { + if (!local) { + ready.resolve(); + } + }); + object1.expirationPeriod = 0.2; + await object1.initialize(undefined); + + object2.expirationPeriod = 0.2; + await object2.initialize(undefined); + + // Wait for ready and then delay + await ready.promise; + await waitForDelay(600); + + // Delay for a few updates + let count = 0; + object1.getUsers().forEach((user) => { + count++; assert( - user.data == undefined, - `user1: Unexpected data object of ${user.data}` + user.status == PresenceStatus.online, + `user[${user.userId}] is ${user.status}` ); - // If not local, we expect that isLocalUser will become true once we receive a message from the other client - if (!local && !user.isLocalUser) { - await waitForDelay(50); - } - assert(user.isLocalUser == true, `user1: should be local`); - object2done.resolve(); - } catch (err) { - object2done.reject(err); - } + }); + + assert(count == 2, `Wrong number of users`); + + disposeAll(); }); - assert(!object1.isInitialized, `presence already initialized`); - const init1 = object1.initialize(); - const init2 = object2.initialize(); - await Promise.all([init1, init2]); - assert(object1.isInitialized, `presence not initialized`); - - // Wait for events to trigger - await Promise.all([object1done.promise, object2done.promise]); - - // cannot check for new clients on same user in `presenceChanged` callback, will evaluate as being equal. - // wait for a sync to happen, and check for new clients with getUser - await waitForDelay(50); - const user1Presence = object1.getUser("user1"); - assert( - user1Presence !== undefined, - "user1 should be defined in object1" - ); - const user2Presence = object2.getUser("user1"); - assert( - user2Presence !== undefined, - "user1 should be defined in object2" - ); - assert( - user1Presence.getConnections().length == 2, - "user should have two clients" - ); - assert( - user2Presence.getConnections().length == 2, - "user should have two clients" - ); - - disposeAll(); - }); - - it("two connections should have their own data/state for same user, user state should be most recent", async () => { - // set same user test host - const mockHost = new SameUserLiveShareTestHost(); - const { object1, object2, disposeAll } = await getObjects( - getTestObjectProvider, - 10000, - true, - mockHost - ); - - const object1Cat = new Deferred(); - const object1Dog = new Deferred(); - object1.on("presenceChanged", async (user, local, clientId) => { - if (user.data?.foo == "cat") { - object1Cat.resolve(); - } else if (user.data?.foo == "dog") { - object1Dog.resolve(); - } + it("isLocalUser should be true for both clients with same userId and contain both clientIds", async () => { + // set same user test host + const mockHost = new SameUserLiveShareTestHost(); + const { object1, object2, disposeAll } = await getObjects( + getTestObjectProvider, + 10000, + true, + mockHost + ); + + const object1done = new Deferred(); + object1.on("presenceChanged", async (user, local) => { + try { + assert(user != null, `user1: Null user arg`); + assert( + user.status == PresenceStatus.online, + `user1: Unexpected presence state of ${user.status}` + ); + assert( + user.data == undefined, + `user1: Unexpected data object of ${user.data}` + ); + // If not local, we expect that isLocalUser will become true once we receive a message from the other client + if (!local && !user.isLocalUser) { + await waitForDelay(50); + } + assert(user.isLocalUser == true, `user1: should be local`); + object1done.resolve(); + } catch (err) { + object1done.reject(err); + } + }); + + const object2done = new Deferred(); + object2.on("presenceChanged", async (user, local) => { + try { + assert(user != null, `user1: Null user arg`); + assert( + user.status == PresenceStatus.online, + `user1: Unexpected presence state of ${user.status}` + ); + assert( + user.data == undefined, + `user1: Unexpected data object of ${user.data}` + ); + // If not local, we expect that isLocalUser will become true once we receive a message from the other client + if (!local && !user.isLocalUser) { + await waitForDelay(50); + } + assert(user.isLocalUser == true, `user1: should be local`); + object2done.resolve(); + } catch (err) { + object2done.reject(err); + } + }); + + assert(!object1.isInitialized, `presence already initialized`); + const init1 = object1.initialize(undefined); + const init2 = object2.initialize(undefined); + await Promise.all([init1, init2]); + assert(object1.isInitialized, `presence not initialized`); + + // Wait for events to trigger + await Promise.all([object1done.promise, object2done.promise]); + + // cannot check for new clients on same user in `presenceChanged` callback, will evaluate as being equal. + // wait for a sync to happen, and check for new clients with getUser + await waitForDelay(50); + const user1Presence = object1.getUser("user1"); + assert( + user1Presence !== undefined, + "user1 should be defined in object1" + ); + const user2Presence = object2.getUser("user1"); + assert( + user2Presence !== undefined, + "user1 should be defined in object2" + ); + assert( + user1Presence.getConnections().length == 2, + "user should have two clients" + ); + assert( + user2Presence.getConnections().length == 2, + "user should have two clients" + ); + + disposeAll(); }); - const object2Cat = new Deferred(); - const object2Dog = new Deferred(); - object2.on("presenceChanged", async (user, local, clientId) => { - if (user.data?.foo == "dog") { - object2Dog.resolve(); - } else if (user.data?.foo == "cat") { - object2Cat.resolve(); - } + it("two connections should have their own data/state for same user, user state should be most recent", async () => { + // set same user test host + const mockHost = new SameUserLiveShareTestHost(); + const { object1, object2, disposeAll } = await getObjects( + getTestObjectProvider, + 10000, + true, + mockHost + ); + + const object1Cat = new Deferred(); + const object1Dog = new Deferred(); + object1.on("presenceChanged", async (user, local, clientId) => { + if (user.data?.foo == "cat") { + object1Cat.resolve(); + } else if (user.data?.foo == "dog") { + object1Dog.resolve(); + } + }); + + const object2Cat = new Deferred(); + const object2Dog = new Deferred(); + object2.on("presenceChanged", async (user, local, clientId) => { + if (user.data?.foo == "dog") { + object2Dog.resolve(); + } else if (user.data?.foo == "cat") { + object2Cat.resolve(); + } + }); + + assert(!object1.isInitialized, `presence already initialized`); + const init1 = object1.initialize(undefined); + const init2 = object2.initialize(undefined); + await Promise.all([init1, init2]); + assert(object1.isInitialized, `presence not initialized`); + + await object1.update({ foo: "cat" }); + // Wait for events to trigger + await Promise.all([object1Cat, object2Cat]); + let object1User = object1.getUser("user1"); + let object2User = object2.getUser("user1"); + assert( + object1User !== undefined, + "user1 should be defined in object1" + ); + assert( + object2User !== undefined, + "user1 should be defined in object2" + ); + assert( + object1User.getConnections().length == 2, + "user should have two clients" + ); + assert( + object2User.getConnections().length == 2, + "user should have two clients" + ); + assert( + object1User.data?.foo == "cat", + `object1 data.foo should be cat, instead is ${object1User.data?.foo}` + ); + assert( + object2User.data?.foo == "cat", + `object2 data.foo should be cat, instead is ${object1User.data?.foo}` + ); + assert( + object1User.getConnection(await object1.clientId())?.data + ?.foo == "cat", + "object1.connection1 data.foo should be cat" + ); + assert( + object1User.getConnection(await object2.clientId())?.data == + undefined, + "object1.connection2 data.foo should be undefined" + ); + assert( + object2User.getConnection(await object1.clientId())?.data + ?.foo == "cat", + "object2.connection1 data.foo should be cat" + ); + assert( + object2User.getConnection(await object2.clientId())?.data == + undefined, + "object2.connection2 data.foo should be undefined" + ); + + await object2.update({ foo: "dog" }); + // Wait for one event loop for remote object1 to receive the change from object2 + await waitForDelay(0); + // redeclare to supress incorrect lint warning, delete to see + object1User = object1.getUser("user1")!; + object2User = object2.getUser("user1")!; + + assert( + object1User.data?.foo == "dog", + `object1 data.foo should be dog, instead is ${object1User.data?.foo}` + ); + assert( + object2User.data?.foo == "dog", + `object2 data.foo should be dog, instead is ${object1User.data?.foo}` + ); + assert( + object1User?.getConnection(await object1.clientId())?.data + ?.foo == "cat", + "object1.connection1.data.foo should STILL be cat" + ); + assert( + object1User?.getConnection(await object2.clientId())?.data + ?.foo == "dog", + "object1.connection2 data.foo should be dog" + ); + assert( + object2User?.getConnection(await object1.clientId())?.data + ?.foo == "cat", + "object2.connection1 data.foo should STILL be cat" + ); + assert( + object2User?.getConnection(await object2.clientId())?.data + ?.foo == "dog", + "object2.connection2 data.foo should be dog" + ); + + disposeAll(); }); - assert(!object1.isInitialized, `presence already initialized`); - const init1 = object1.initialize(); - const init2 = object2.initialize(); - await Promise.all([init1, init2]); - assert(object1.isInitialized, `presence not initialized`); - - await object1.update({ foo: "cat" }); - // Wait for events to trigger - await Promise.all([object1Cat, object2Cat]); - let object1User = object1.getUser("user1"); - let object2User = object2.getUser("user1"); - assert(object1User !== undefined, "user1 should be defined in object1"); - assert(object2User !== undefined, "user1 should be defined in object2"); - assert( - object1User.getConnections().length == 2, - "user should have two clients" - ); - assert( - object2User.getConnections().length == 2, - "user should have two clients" - ); - assert( - object1User.data?.foo == "cat", - `object1 data.foo should be cat, instead is ${object1User.data?.foo}` - ); - assert( - object2User.data?.foo == "cat", - `object2 data.foo should be cat, instead is ${object1User.data?.foo}` - ); - assert( - object1User.getConnection(await object1.clientId())?.data?.foo == - "cat", - "object1.connection1 data.foo should be cat" - ); - assert( - object1User.getConnection(await object2.clientId())?.data == - undefined, - "object1.connection2 data.foo should be undefined" - ); - assert( - object2User.getConnection(await object1.clientId())?.data?.foo == - "cat", - "object2.connection1 data.foo should be cat" - ); - assert( - object2User.getConnection(await object2.clientId())?.data == - undefined, - "object2.connection2 data.foo should be undefined" - ); - - await object2.update({ foo: "dog" }); - // Wait for one event loop for remote object1 to receive the change from object2 - await waitForDelay(0); - // redeclare to supress incorrect lint warning, delete to see - object1User = object1.getUser("user1")!; - object2User = object2.getUser("user1")!; - - assert( - object1User.data?.foo == "dog", - `object1 data.foo should be dog, instead is ${object1User.data?.foo}` - ); - assert( - object2User.data?.foo == "dog", - `object2 data.foo should be dog, instead is ${object1User.data?.foo}` - ); - assert( - object1User?.getConnection(await object1.clientId())?.data?.foo == - "cat", - "object1.connection1.data.foo should STILL be cat" - ); - assert( - object1User?.getConnection(await object2.clientId())?.data?.foo == - "dog", - "object1.connection2 data.foo should be dog" - ); - assert( - object2User?.getConnection(await object1.clientId())?.data?.foo == - "cat", - "object2.connection1 data.foo should STILL be cat" - ); - assert( - object2User?.getConnection(await object2.clientId())?.data?.foo == - "dog", - "object2.connection2 data.foo should be dog" - ); - - disposeAll(); - }); - - it("test offline timeout for user and connections", async () => { - // set same user test host - const mockHost = new SameUserLiveShareTestHost(); - const { object1, object2, disposeAll, disposeObject1, disposeObject2 } = - await getObjects(getTestObjectProvider, 10000, true, mockHost); - - assert(!object1.isInitialized, `presence already initialized`); - const init1 = object1.initialize(); - const init2 = object2.initialize(); - await Promise.all([init1, init2]); - assert(object1.isInitialized, `presence not initialized`); - - // Wait for events to trigger - let object1User = object1.getUser("user1"); - let object2User = object2.getUser("user1"); - assert(object1User !== undefined, "user1 should be defined in object1"); - assert(object2User !== undefined, "user1 should be defined in object2"); - assert( - object1User.getConnections().length == 2, - "user should have two clients" - ); - assert( - object2User.getConnections().length == 2, - "user should have two clients" - ); - - const object2ClientId = await object2.clientId(); - - disposeObject2(); - object1.expirationPeriod = 0.1; - assert( - object1User.getConnection(object2ClientId)?.state == - PresenceState.online, - "object2 should still be online from object1's perspective" - ); - await waitForDelay(150); - assert( - object1User.getConnection(object2ClientId)?.state == - PresenceState.offline, - "object2 should be offline" - ); - disposeObject1(); - }); -}); + it("test away timeout for user and connections", async () => { + // set same user test host + const mockHost = new SameUserLiveShareTestHost(); + const { + object1, + object2, + disposeAll, + disposeObject1, + disposeObject2, + } = await getObjects(getTestObjectProvider, 10000, true, mockHost); + + assert(!object1.isInitialized, `presence already initialized`); + const init1 = object1.initialize(undefined); + const init2 = object2.initialize(undefined); + await Promise.all([init1, init2]); + assert(object1.isInitialized, `presence not initialized`); + + // Wait for events to trigger + let object1User = object1.getUser("user1"); + let object2User = object2.getUser("user1"); + assert( + object1User !== undefined, + "user1 should be defined in object1" + ); + assert( + object2User !== undefined, + "user1 should be defined in object2" + ); + assert( + object1User.getConnections().length == 2, + "user should have two clients" + ); + assert( + object2User.getConnections().length == 2, + "user should have two clients" + ); + + const object2ClientId = await object2.clientId(); + + disposeObject2(); + object1.expirationPeriod = 0.1; + assert( + object1User.getConnection(object2ClientId)?.status == + PresenceStatus.online, + "object2 should still be online from object1's perspective" + ); + await waitForDelay(150); + assert( + object1User.getConnection(object2ClientId)?.status == + PresenceStatus.away, + "object2 should be away" + ); + disposeObject1(); + }); + } +); class SameUserLiveShareTestHost implements ILiveShareHost { - private test = TestLiveShareHost.create(); + private test = TestLiveShareHost.create(new MockTokenProvider()); getFluidTenantInfo(): Promise { return this.test.getFluidTenantInfo(); } diff --git a/packages/live-share-turbo/src/test/LiveShareTurboClient.spec.ts b/packages/live-share/src/test/LiveShareClient.spec.ts similarity index 74% rename from packages/live-share-turbo/src/test/LiveShareTurboClient.spec.ts rename to packages/live-share/src/test/LiveShareClient.spec.ts index 27e139116..843ad4bc8 100644 --- a/packages/live-share-turbo/src/test/LiveShareTurboClient.spec.ts +++ b/packages/live-share/src/test/LiveShareClient.spec.ts @@ -4,23 +4,16 @@ */ import { strict as assert } from "assert"; -import { - IFluidContainer, - LoadableObjectClassRecord, - SharedMap, -} from "fluid-framework"; -import { LiveEvent, TestLiveShareHost } from "@microsoft/live-share"; -import { LiveShareTurboClient } from "../LiveShareTurboClient"; +import { ContainerSchema, IFluidContainer } from "fluid-framework"; +import { SharedMap } from "fluid-framework/legacy"; import { AzureContainerServices } from "@fluidframework/azure-client"; +import { TestLiveShareHost } from "../TestLiveShareHost.js"; +import { LiveShareClient } from "../LiveShareClient.js"; +import { LiveEvent } from "../LiveEvent.js"; +import { LiveState } from "../LiveState.js"; +import { InsecureTokenProvider } from "@fluidframework/test-runtime-utils/internal"; -describe("LiveShareTurboClient", () => { - (window.performance as any).mark = () => { - return {}; - }; - (window.performance as any).measure = () => { - return {}; - }; - +describe("LiveShareClient dynamic objects", () => { let containerId: string | undefined; const getContainerId = (): string | undefined => { return containerId; @@ -28,9 +21,16 @@ describe("LiveShareTurboClient", () => { const setContainerId = (newContainerId: string) => { containerId = newContainerId; }; - const host = TestLiveShareHost.create(getContainerId, setContainerId); - let client1: LiveShareTurboClient; - let client2: LiveShareTurboClient; + const host = TestLiveShareHost.create( + new InsecureTokenProvider("", { + id: "testId", + name: "Test User", + }), + getContainerId, + setContainerId + ); + let client1: LiveShareClient; + let client2: LiveShareClient; const testMapKey = "TEST-MAP-KEY"; const testLiveEventKey = "TEST-LIVE-EVENT-KEY"; @@ -46,14 +46,16 @@ describe("LiveShareTurboClient", () => { }; beforeEach(async () => { - client1 = new LiveShareTurboClient(host); - client2 = new LiveShareTurboClient(host); - const initialObjects: LoadableObjectClassRecord = { - [testLiveEventKey]: LiveEvent, + client1 = new LiveShareClient(host); + client2 = new LiveShareClient(host); + const schema: ContainerSchema = { + initialObjects: { + [testLiveEventKey]: LiveEvent, + }, }; containerId = undefined; - results1 = await client1.join(initialObjects); - results2 = await client2.join(initialObjects); + results1 = await client1.join(schema); + results2 = await client2.join(schema); }); it("Containers should be configured correctly", async () => { @@ -62,14 +64,14 @@ describe("LiveShareTurboClient", () => { .length === 1, "Incorrect number of containers created" ); - assert( - !!client1.results && !!client2.results, - "client.results results not defined" - ); assert( !!results1.container || !!results1.services, "client1 results container or services are not defined" ); + + // state map not initialized until dynamic features are used. + await client1.getDDS("test", LiveState); + await client2.getDDS("test", LiveState); assert( !!client1.stateMap || !!client2.stateMap, "stateMap is not defined" @@ -109,10 +111,10 @@ describe("LiveShareTurboClient", () => { dds1 !== undefined && dds2 !== undefined, "test map(s) not defined" ); - // Only one should be marked as created + // two should be marked as created, one gets discarded after consensus is reached assert( [object1Created, object2Created].filter((created) => created) - .length === 1, + .length === 2, "Incorrect number of objects created" ); }); diff --git a/packages/live-share/src/test/LiveState.spec.ts b/packages/live-share/src/test/LiveState.spec.ts index 5c467292f..d25cc4103 100644 --- a/packages/live-share/src/test/LiveState.spec.ts +++ b/packages/live-share/src/test/LiveState.spec.ts @@ -4,47 +4,63 @@ */ import { strict as assert } from "assert"; -import { requestFluidObject } from "@fluidframework/runtime-utils"; -import { ITestObjectProvider } from "@fluidframework/test-utils"; -import { describeNoCompat } from "@fluidframework/test-version-utils"; -import { LiveState } from "../LiveState"; -import { Deferred } from "../internals"; -import { getLiveDataObjectClass } from "../schema-injection-utils"; -import { MockLiveShareRuntime } from "./MockLiveShareRuntime"; +import { + ITestObjectProvider, + fluidEntryPoint, + getContainerEntryPointBackCompat, +} from "@fluidframework/test-utils/internal"; +import { LiveState } from "../LiveState.js"; +import { Deferred } from "../internals/Deferred.js"; +import { getLiveDataObjectKind } from "../internals/schema-injection-utils.js"; +import { MockLiveShareRuntime } from "../internals/mock/MockLiveShareRuntime.js"; +import { + describeCompat, + ITestObjectProviderOptions, +} from "@live-share-private/test-utils"; interface TestStateData { status: string; value: string; } -async function getObjects(getTestObjectProvider) { +async function getObjects( + getTestObjectProvider: ( + options?: ITestObjectProviderOptions + ) => ITestObjectProvider +) { // Temporarily change update interval let liveRuntime1 = new MockLiveShareRuntime(false); let liveRuntime2 = new MockLiveShareRuntime(false); - let ObjectProxy1: any = getLiveDataObjectClass< - LiveState - >(LiveState, liveRuntime1); - let ObjectProxy2: any = getLiveDataObjectClass< - LiveState - >(LiveState, liveRuntime2); + let ObjectProxy1: any = getLiveDataObjectKind>( + LiveState, + liveRuntime1 + ); + let ObjectProxy2: any = getLiveDataObjectKind>( + LiveState, + liveRuntime2 + ); await liveRuntime1.start(); await liveRuntime2.start(); let provider: ITestObjectProvider = getTestObjectProvider(); - let container1 = await provider.createContainer(ObjectProxy1.factory); - let object1 = await requestFluidObject>( - container1, - "default" + let container1 = await provider.createContainer( + ObjectProxy1.factory as fluidEntryPoint ); + let object1 = + await getContainerEntryPointBackCompat>( + container1 + ); - let container2 = await provider.loadContainer(ObjectProxy2.factory); - let object2 = await requestFluidObject>( - container2, - "default" + let container2 = await provider.loadContainer( + ObjectProxy2.factory as fluidEntryPoint ); + let object2 = + await getContainerEntryPointBackCompat>( + container2 + ); // need to be connected to send signals if (!container1.connect) { await new Promise((resolve) => container1.once("connected", resolve)); @@ -72,167 +88,174 @@ const mockDefaultValue: TestStateData = { value: "defaultValue", }; -describeNoCompat("LiveState", (getTestObjectProvider) => { - it("Should changeState() to new state and value", async () => { - const { object1, object2, dispose } = await getObjects( - getTestObjectProvider - ); - const object1done = new Deferred(); - object1.on("stateChanged", (state, local) => { - try { - if (local) { - assert( - typeof state == "object", - `object1: data is not an object` - ); - assert( - typeof state.status == "string", - `object1: state.status is not a string` - ); - assert( - typeof state.value == "string", - `object1: state.value is not a string` - ); - assert( - state.status === "newState", - `object1: status == '${JSON.stringify(state.status)}'` - ); - assert( - state.value === "newValue", - `object1: value == '${JSON.stringify(state.value)}'` - ); - object1done.resolve(); +describeCompat( + "LiveState", + ( + getTestObjectProvider: ( + options?: ITestObjectProviderOptions + ) => ITestObjectProvider + ) => { + it("Should changeState() to new state and value", async () => { + const { object1, object2, dispose } = await getObjects( + getTestObjectProvider + ); + const object1done = new Deferred(); + object1.on("stateChanged", (state, local) => { + try { + if (local) { + assert( + typeof state == "object", + `object1: data is not an object` + ); + assert( + typeof state.status == "string", + `object1: state.status is not a string` + ); + assert( + typeof state.value == "string", + `object1: state.value is not a string` + ); + assert( + state.status === "newState", + `object1: status == '${JSON.stringify(state.status)}'` + ); + assert( + state.value === "newValue", + `object1: value == '${JSON.stringify(state.value)}'` + ); + object1done.resolve(); + } + } catch (err) { + object1done.reject(err); } - } catch (err) { - object1done.reject(err); - } - }); + }); - const object2done = new Deferred(); - object2.on("stateChanged", (state, local) => { - try { - if (!local) { - assert( - typeof state == "object", - `object2: data is not an object` - ); - assert( - typeof state.status == "string", - `object2: state.status is not a string` - ); - assert( - typeof state.value == "string", - `object2: state.value is not a string` - ); - assert( - state.status == "newState", - `object1: status == '${JSON.stringify(state)}'` - ); - assert( - state.value == "newValue", - `object1: value == '${JSON.stringify(state)}'` - ); - object2done.resolve(); + const object2done = new Deferred(); + object2.on("stateChanged", (state, local) => { + try { + if (!local) { + assert( + typeof state == "object", + `object2: data is not an object` + ); + assert( + typeof state.status == "string", + `object2: state.status is not a string` + ); + assert( + typeof state.value == "string", + `object2: state.value is not a string` + ); + assert( + state.status == "newState", + `object1: status == '${JSON.stringify(state)}'` + ); + assert( + state.value == "newValue", + `object1: value == '${JSON.stringify(state)}'` + ); + object2done.resolve(); + } + } catch (err) { + object2done.reject(err); } - } catch (err) { - object2done.reject(err); - } - }); - let init1 = object1.initialize(mockDefaultValue); - let init2 = object2.initialize(mockDefaultValue); + }); + let init1 = object1.initialize(mockDefaultValue); + let init2 = object2.initialize(mockDefaultValue); - await Promise.all([init1, init2]); + await Promise.all([init1, init2]); - assert( - object1.state.status == mockDefaultValue.status, - `object1: status == '${object1.state.status}'` - ); + assert( + object1.state.status == mockDefaultValue.status, + `object1: status == '${object1.state.status}'` + ); - await object1.set({ status: "newState", value: "newValue" }); + await object1.set({ status: "newState", value: "newValue" }); - // Wait for events to trigger - await Promise.all([object1done.promise, object2done.promise]); + // Wait for events to trigger + await Promise.all([object1done.promise, object2done.promise]); - dispose(); - }); + dispose(); + }); - it("Should changeState() to new value for same state", async () => { - const { object1, object2, dispose } = await getObjects( - getTestObjectProvider - ); - const done = new Deferred(); - object1.on("stateChanged", (state, local) => { - try { - if (!local) { - assert( - typeof state == "object", - `object1: data is not an object` - ); - assert( - typeof state.status == "string", - `object1: state.status is not a string` - ); - assert( - typeof state.value == "string", - `object1: state.value is not a string` - ); - assert( - state.status == "testState", - `object1: status == '${state.status}'` - ); - assert( - state.value == "secondValue", - `object1: value == '${state.value}'` - ); - done.resolve(); + it("Should changeState() to new value for same state", async () => { + const { object1, object2, dispose } = await getObjects( + getTestObjectProvider + ); + const done = new Deferred(); + object1.on("stateChanged", (state, local) => { + try { + if (!local) { + assert( + typeof state == "object", + `object1: data is not an object` + ); + assert( + typeof state.status == "string", + `object1: state.status is not a string` + ); + assert( + typeof state.value == "string", + `object1: state.value is not a string` + ); + assert( + state.status == "testState", + `object1: status == '${state.status}'` + ); + assert( + state.value == "secondValue", + `object1: value == '${state.value}'` + ); + done.resolve(); + } + } catch (err) { + done.reject(err); } - } catch (err) { - done.reject(err); - } - }); - const init1 = object1.initialize(mockDefaultValue); - - object2.on("stateChanged", (state, local) => { - try { - if (!local) { - assert( - typeof state == "object", - `object2: data is not an object` - ); - assert( - typeof state.status == "string", - `object2: state.status is not a string` - ); - assert( - typeof state.value == "string", - `object2: state.value is not a string` - ); - assert( - state.status == "testState", - `object2: status == '${state.status}'` - ); - assert( - state.value == "firstValue", - `object2: value == '${state.value}'` - ); - object2.set({ - status: "testState", - value: "secondValue", - }); + }); + const init1 = object1.initialize(mockDefaultValue); + + object2.on("stateChanged", (state, local) => { + try { + if (!local) { + assert( + typeof state == "object", + `object2: data is not an object` + ); + assert( + typeof state.status == "string", + `object2: state.status is not a string` + ); + assert( + typeof state.value == "string", + `object2: state.value is not a string` + ); + assert( + state.status == "testState", + `object2: status == '${state.status}'` + ); + assert( + state.value == "firstValue", + `object2: value == '${state.value}'` + ); + object2.set({ + status: "testState", + value: "secondValue", + }); + } + } catch (err) { + done.reject(err); } - } catch (err) { - done.reject(err); - } - }); - const init2 = object2.initialize(mockDefaultValue); + }); + const init2 = object2.initialize(mockDefaultValue); - await Promise.all([init1, init2]); + await Promise.all([init1, init2]); - await object1.set({ status: "testState", value: "firstValue" }); + await object1.set({ status: "testState", value: "firstValue" }); - // Wait for events to trigger - await done.promise; + // Wait for events to trigger + await done.promise; - dispose(); - }); -}); + dispose(); + }); + } +); diff --git a/packages/live-share/src/test/LiveTimer.spec.ts b/packages/live-share/src/test/LiveTimer.spec.ts index 6b239da0d..24fb1ba3c 100644 --- a/packages/live-share/src/test/LiveTimer.spec.ts +++ b/packages/live-share/src/test/LiveTimer.spec.ts @@ -4,27 +4,36 @@ */ import { strict as assert } from "assert"; -import { requestFluidObject } from "@fluidframework/runtime-utils"; -import { ITestObjectProvider } from "@fluidframework/test-utils"; -import { describeNoCompat } from "@fluidframework/test-version-utils"; -import { LiveTimer } from "../LiveTimer"; -import { Deferred, waitForDelay } from "../internals"; -import { getLiveDataObjectClass } from "../schema-injection-utils"; -import { MockLiveShareRuntime } from "./MockLiveShareRuntime"; +import { + ITestObjectProvider, + fluidEntryPoint, + getContainerEntryPointBackCompat, +} from "@fluidframework/test-utils/internal"; +import { LiveTimer } from "../LiveTimer.js"; +import { Deferred } from "../internals/Deferred.js"; +import { getLiveDataObjectKind } from "../internals/schema-injection-utils.js"; +import { MockLiveShareRuntime } from "../internals/mock/MockLiveShareRuntime.js"; +import { + describeCompat, + ITestObjectProviderOptions, +} from "@live-share-private/test-utils"; +import { waitForDelay } from "../internals/utils.js"; async function getObjects( - getTestObjectProvider, + getTestObjectProvider: ( + options?: ITestObjectProviderOptions + ) => ITestObjectProvider, updateInterval: number = 10000 ) { // Temporarily change update interval let liveRuntime1 = new MockLiveShareRuntime(false, updateInterval); let liveRuntime2 = new MockLiveShareRuntime(false, updateInterval); - let ObjectProxy1: any = getLiveDataObjectClass( + let ObjectProxy1: any = getLiveDataObjectKind( LiveTimer, liveRuntime1 ); - let ObjectProxy2: any = getLiveDataObjectClass( + let ObjectProxy2: any = getLiveDataObjectKind( LiveTimer, liveRuntime2 ); @@ -34,11 +43,15 @@ async function getObjects( let provider: ITestObjectProvider = getTestObjectProvider(); - let container1 = await provider.createContainer(ObjectProxy1.factory); - let object1 = await requestFluidObject(container1, "default"); + let container1 = await provider.createContainer( + ObjectProxy1.factory as fluidEntryPoint + ); + let object1 = await getContainerEntryPointBackCompat(container1); - let container2 = await provider.loadContainer(ObjectProxy2.factory); - let object2 = await requestFluidObject(container2, "default"); + let container2 = await provider.loadContainer( + ObjectProxy2.factory as fluidEntryPoint + ); + let object2 = await getContainerEntryPointBackCompat(container2); // need to be connected to send signals if (!container1.connect) { await new Promise((resolve) => container1.once("connected", resolve)); @@ -62,256 +75,269 @@ async function getObjects( } const milliTolerance = 31; -describeNoCompat("LiveTimer", (getTestObjectProvider) => { - it("Should raise local and remote start events", async () => { - const { object1, object2, dispose } = await getObjects( - getTestObjectProvider - ); - const now = new Date().getTime(); - const object1done = new Deferred(); - object1.on("started", (config, local) => { - try { - assert(local == true, `Not a local event`); - assert(config != null, `Null config arg`); - assert(config.clientId != null, `Missing clientId`); - assert( - typeof config.configChangedAt == "number", - `Missing timestamp` - ); - assert(config.configChangedAt >= now, `Timestamp too old`); - object1done.resolve(); - } catch (err) { - object1done.reject(err); - } - }); - await object1.initialize(); +describeCompat( + "LiveTimer", + ( + getTestObjectProvider: ( + options?: ITestObjectProviderOptions + ) => ITestObjectProvider + ) => { + it("Should raise local and remote start events", async () => { + const { object1, object2, dispose } = await getObjects( + getTestObjectProvider + ); + const now = new Date().getTime(); + const object1done = new Deferred(); + object1.on("started", (config, local) => { + try { + assert(local == true, `Not a local event`); + assert(config != null, `Null config arg`); + assert(config.clientId != null, `Missing clientId`); + assert( + typeof config.configChangedAt == "number", + `Missing timestamp` + ); + assert(config.configChangedAt >= now, `Timestamp too old`); + object1done.resolve(); + } catch (err) { + object1done.reject(err); + } + }); + await object1.initialize(); - const object2done = new Deferred(); - object2.on("started", (config, local) => { - try { - assert(local == false, `Unexpected local event`); - assert(config != null, `Null config arg`); - assert(config.clientId != null, `Missing clientId`); - assert( - typeof config.configChangedAt == "number", - `Missing timestamp` - ); - assert(config.configChangedAt >= now, `Timestamp too old`); - object2done.resolve(); - } catch (err) { - object2done.reject(err); - } + const object2done = new Deferred(); + object2.on("started", (config, local) => { + try { + assert(local == false, `Unexpected local event`); + assert(config != null, `Null config arg`); + assert(config.clientId != null, `Missing clientId`); + assert( + typeof config.configChangedAt == "number", + `Missing timestamp` + ); + assert(config.configChangedAt >= now, `Timestamp too old`); + object2done.resolve(); + } catch (err) { + object2done.reject(err); + } + }); + await object2.initialize(); + + await object1.start(1); + + // Wait for events to trigger + await Promise.all([object1done.promise, object2done.promise]); + + dispose(); }); - await object2.initialize(); - await object1.start(1); - - // Wait for events to trigger - await Promise.all([object1done.promise, object2done.promise]); - - dispose(); - }); - - it("Should throw error if already initialized", async () => { - const { object1, object2, dispose } = await getObjects( - getTestObjectProvider - ); - await object1.initialize(); - try { - // Ensure initialized - assert(object1.isInitialized, `not initialized`); - - // Try second call to initialize. + it("Should throw error if already initialized", async () => { + const { object1, object2, dispose } = await getObjects( + getTestObjectProvider + ); await object1.initialize(); - assert(false, `exception not thrown`); - } catch (err) { - console.error("there was an error"); - } - - object1.dispose(); - object2.dispose(); - }); - - it("Should throw error if start(duration) called before initialize", async () => { - const { object1, object2, dispose } = await getObjects( - getTestObjectProvider - ); - try { - await object1.start(10); - assert(false, `exception not thrown`); - } catch (err) { - console.error("there was an error"); - } - - dispose(); - }); - - it("pause and play, check resumes at correct position", async () => { - const { object1, object2, dispose } = await getObjects( - getTestObjectProvider - ); - const object1done = new Deferred(); - let pausePosition = 0; - object1.on("paused", (config, local) => { - pausePosition = config.position; - }); - object1.on("played", (config, local) => { try { - assert(pausePosition !== 0, "never paused"); - assert( - config.position === pausePosition, - `did not resume at pause position` - ); - object1done.resolve(); - } catch (err) { - object1done.reject(err); - } - }); - await object1.initialize(); + // Ensure initialized + assert(object1.isInitialized, `not initialized`); - const object2done = new Deferred(); - object2.on("played", (config, local) => { - try { - assert(pausePosition !== 0, "never paused"); - assert( - config.position === pausePosition, - `did not resume at pause position` - ); - object2done.resolve(); + // Try second call to initialize. + await object1.initialize(); + assert(false, `exception not thrown`); } catch (err) { - object2done.reject(err); + console.error("there was an error"); } - }); - await object2.initialize(); - - await object1.start(50); - await waitForDelay(20); - await object1.pause(); - await waitForDelay(20); - await object2.play(); - - // Wait for events to trigger - await Promise.all([object1done.promise, object2done.promise]); - - dispose(); - }); - - it("start overrides existing timer", async () => { - const { object1, object2, dispose } = await getObjects( - getTestObjectProvider - ); - const testDone = new Deferred(); - let startedCounter = 0; - let finishedCounter = 0; - - object2.on("started", (config, local) => { - startedCounter += 1; - }); - object2.on("finished", (config) => { - finishedCounter += 1; + + object1.dispose(); + object2.dispose(); }); - let init1 = object1.initialize(); - let init2 = object2.initialize(); - await Promise.all([init1, init2]); - - await object1.start(40); - await waitForDelay(10); - await object1.start(40); - await waitForDelay(10); - await object1.start(20); - await waitForDelay(40); - testDone.resolve(); - - // Wait for events to trigger - await testDone.promise; - assert(startedCounter === 3, `expect 3, got ${startedCounter}`); - assert(finishedCounter === 1, `expect 1, got ${finishedCounter}`); - - dispose(); - }); - - it("finish callback called within 31ms of ending", async () => { - const { object1, object2, dispose } = await getObjects( - getTestObjectProvider - ); - const now = new Date().getTime(); - const object1done = new Deferred(); - object1.on("finished", (config) => { + it("Should throw error if start(duration) called before initialize", async () => { + const { object1, object2, dispose } = await getObjects( + getTestObjectProvider + ); try { - assert(config != null, `Null config arg`); - assert(config.clientId != null, `Missing clientId`); - assert( - typeof config.configChangedAt == "number", - `Missing timestamp` - ); - const milliDifference = - config.configChangedAt - now - config.duration; - assert(milliDifference <= milliTolerance, `${milliDifference}`); - object1done.resolve(); + await object1.start(10); + assert(false, `exception not thrown`); } catch (err) { - object1done.reject(err); + console.error("there was an error"); } + + dispose(); }); - await object1.initialize(); - const object2done = new Deferred(); - object2.on("finished", (config) => { - try { - assert(config != null, `Null config arg`); - assert(config.clientId != null, `Missing clientId`); - assert( - typeof config.configChangedAt == "number", - `Missing timestamp` - ); - const milliDifference = - config.configChangedAt - now - config.duration; - assert(milliDifference <= milliTolerance, `${milliDifference}`); - object2done.resolve(); - } catch (err) { - object2done.reject(err); - } + it("pause and play, check resumes at correct position", async () => { + const { object1, object2, dispose } = await getObjects( + getTestObjectProvider + ); + const object1done = new Deferred(); + let pausePosition = 0; + object1.on("paused", (config, local) => { + pausePosition = config.position; + }); + object1.on("played", (config, local) => { + try { + assert(pausePosition !== 0, "never paused"); + assert( + config.position === pausePosition, + `did not resume at pause position` + ); + object1done.resolve(); + } catch (err) { + object1done.reject(err); + } + }); + await object1.initialize(); + + const object2done = new Deferred(); + object2.on("played", (config, local) => { + try { + assert(pausePosition !== 0, "never paused"); + assert( + config.position === pausePosition, + `did not resume at pause position` + ); + object2done.resolve(); + } catch (err) { + object2done.reject(err); + } + }); + await object2.initialize(); + + await object1.start(50); + await waitForDelay(20); + await object1.pause(); + await waitForDelay(20); + await object2.play(); + + // Wait for events to trigger + await Promise.all([object1done.promise, object2done.promise]); + + dispose(); }); - await object2.initialize(); - - await object1.start(100); - - // Wait for events to trigger - await Promise.all([object1done.promise, object2done.promise]); - - dispose(); - }); - - it("500 milli tick rate", async () => { - const { object1, object2, dispose } = await getObjects( - getTestObjectProvider - ); - const object1done = new Deferred(); - object1.tickRate = 500; - let tickCounter = 0; - object1.on("onTick", () => { - tickCounter += 1; - console.log("tickCounter", tickCounter); + + it("start overrides existing timer", async () => { + const { object1, object2, dispose } = await getObjects( + getTestObjectProvider + ); + const testDone = new Deferred(); + let startedCounter = 0; + let finishedCounter = 0; + + object2.on("started", (config, local) => { + startedCounter += 1; + }); + object2.on("finished", (config) => { + finishedCounter += 1; + }); + + let init1 = object1.initialize(); + let init2 = object2.initialize(); + await Promise.all([init1, init2]); + + await object1.start(40); + await waitForDelay(10); + await object1.start(40); + await waitForDelay(10); + await object1.start(20); + await waitForDelay(40); + testDone.resolve(); + + // Wait for events to trigger + await testDone.promise; + assert(startedCounter === 3, `expect 3, got ${startedCounter}`); + assert(finishedCounter === 1, `expect 1, got ${finishedCounter}`); + + dispose(); }); - object1.on("finished", (config) => { - console.log(config); - if (tickCounter == 3) { - object1done.resolve(); - } else { - object1done.reject(tickCounter); - } + it("finish callback called within 31ms of ending", async () => { + const { object1, object2, dispose } = await getObjects( + getTestObjectProvider + ); + const now = new Date().getTime(); + const object1done = new Deferred(); + object1.on("finished", (config) => { + try { + assert(config != null, `Null config arg`); + assert(config.clientId != null, `Missing clientId`); + assert( + typeof config.configChangedAt == "number", + `Missing timestamp` + ); + const milliDifference = + config.configChangedAt - now - config.duration; + assert( + milliDifference <= milliTolerance, + `${milliDifference}` + ); + object1done.resolve(); + } catch (err) { + object1done.reject(err); + } + }); + await object1.initialize(); + + const object2done = new Deferred(); + object2.on("finished", (config) => { + try { + assert(config != null, `Null config arg`); + assert(config.clientId != null, `Missing clientId`); + assert( + typeof config.configChangedAt == "number", + `Missing timestamp` + ); + const milliDifference = + config.configChangedAt - now - config.duration; + assert( + milliDifference <= milliTolerance, + `${milliDifference}` + ); + object2done.resolve(); + } catch (err) { + object2done.reject(err); + } + }); + await object2.initialize(); + + await object1.start(100); + + // Wait for events to trigger + await Promise.all([object1done.promise, object2done.promise]); + + dispose(); }); - await object1.initialize(); - await object1.start(1600); + it("500 milli tick rate", async () => { + const { object1, object2, dispose } = await getObjects( + getTestObjectProvider + ); + const object1done = new Deferred(); + object1.tickRate = 500; + let tickCounter = 0; + object1.on("onTick", () => { + tickCounter += 1; + console.log("tickCounter", tickCounter); + }); + + object1.on("finished", (config) => { + console.log(config); + if (tickCounter == 3) { + object1done.resolve(); + } else { + object1done.reject(tickCounter); + } + }); - // initialized for test setup - object2.initialize(); + await object1.initialize(); + await object1.start(1600); + + // initialized for test setup + object2.initialize(); - // Wait for events to trigger - await object1done.promise; + // Wait for events to trigger + await object1done.promise; - dispose(); - }); -}); + dispose(); + }); + } +); diff --git a/packages/live-share/src/test/TimestampProvider.spec.ts b/packages/live-share/src/test/TimestampProvider.spec.ts index 7199dd445..61aa1fcb5 100644 --- a/packages/live-share/src/test/TimestampProvider.spec.ts +++ b/packages/live-share/src/test/TimestampProvider.spec.ts @@ -4,9 +4,9 @@ */ import { strict as assert } from "assert"; -import { INtpTimeInfo } from "../interfaces"; -import { TimestampProvider } from "../TimestampProvider"; -import { Deferred } from "../internals"; +import { INtpTimeInfo } from "../interfaces.js"; +import { TimestampProvider } from "../TimestampProvider.js"; +import { Deferred } from "../internals/Deferred.js"; class TestTimestampProvider extends TimestampProvider { private _onGetNtpTime: () => Promise; diff --git a/packages/live-share/src/test/utils.spec.ts b/packages/live-share/src/test/utils.spec.ts index 52dc45821..0560c91f9 100644 --- a/packages/live-share/src/test/utils.spec.ts +++ b/packages/live-share/src/test/utils.spec.ts @@ -1,10 +1,9 @@ import { strict as assert } from "assert"; import { + TimeoutError, timeoutRequest, - Deferred, waitForResult, - TimeoutError, -} from "../internals"; +} from "../internals/utils.js"; describe("timeoutRequest", function () { it("should return the result when request is successful within timeout", async () => { @@ -40,25 +39,6 @@ describe("timeoutRequest", function () { ); } }); - - it("should call lateFinish when request finishes after timeout", async () => { - const lateFinishCalled = new Deferred(); - const fnRequest = () => { - const lateRequestFinished = new Deferred(); - setTimeout(() => { - lateRequestFinished.resolve(); - }, 20); - return lateRequestFinished.promise; - }; - try { - await timeoutRequest(fnRequest, 10, () => { - lateFinishCalled.resolve(); - }); - } catch (error) { - // We expect a timeout error here, so we just swallow it - } - await lateFinishCalled.promise; - }); }); describe("waitForResult", function () { @@ -67,14 +47,10 @@ describe("waitForResult", function () { const fnRequest = async () => "response"; const fnValidateResponse = (result: string) => result === "response" ? { response: expectedResult } : null; - const fnTimeout = (reason: unknown) => new TimeoutError(); const result = await waitForResult( fnRequest, fnValidateResponse, - fnTimeout, [10], - undefined, - undefined, 10 ); assert(result === expectedResult, "unexpected result"); @@ -87,14 +63,10 @@ describe("waitForResult", function () { attempt++ === 1 ? "response" : "invalid"; const fnValidateResponse = (result: string) => result === "response" ? { response: expectedResult } : null; - const fnTimeout = (reason: unknown) => new TimeoutError(); const result = await waitForResult( fnRequest, fnValidateResponse, - fnTimeout, [10, 20], - undefined, - undefined, 10 ); assert(result === expectedResult, "unexpected result"); @@ -106,9 +78,8 @@ describe("waitForResult", function () { attempt++ === 2 ? "response" : "invalid"; const fnValidateResponse = (result: string) => result === "response" ? { response: "successful" } : null; - const fnTimeout = (reason: unknown) => new TimeoutError(); try { - await waitForResult(fnRequest, fnValidateResponse, fnTimeout, [10]); + await waitForResult(fnRequest, fnValidateResponse, [10]); assert.fail("Expected an error to be thrown"); } catch (error) { assert(error instanceof Error, "Expected an instance of Error"); @@ -126,79 +97,8 @@ describe("waitForResult", function () { const fnValidateResponse = (result: string) => ({ response: "successful", }); - const fnTimeout = (reason: unknown) => new TimeoutError(); - const fnRequestError = (error: unknown) => - error instanceof Error ? error : null; - try { - await waitForResult( - fnRequest, - fnValidateResponse, - fnTimeout, - [10], - fnRequestError, - undefined, - 10 - ); - assert.fail("Expected an error to be thrown"); - } catch (error) { - assert(error instanceof Error, "Expected an instance of Error"); - assert( - error.message === "request failed", - "unexpected error message" - ); - } - }); - - it("should retry when the request fails, retrySchedule allows more attempts, and fnRequestError doesn't reject", async () => { - const expectedResult = "successful"; - let attempt = 0; - const fnRequest = async () => { - if (attempt++ === 0) { - throw new Error("request failed"); - } else { - return "response"; - } - }; - const fnValidateResponse = (result: string) => - result === "response" ? { response: expectedResult } : null; - const fnTimeout = (reason: unknown) => new TimeoutError(); - const fnRequestError = (error: unknown) => null; - const result = await waitForResult( - fnRequest, - fnValidateResponse, - fnTimeout, - [10, 20], - fnRequestError, - undefined, - 10 - ); - assert(result === expectedResult, "unexpected result"); - }); - - it("should fail when the request fails, retrySchedule allows more attempts, but fnRequestError rejects", async () => { - let attempt = 0; - const fnRequest = async () => { - if (attempt++ === 0) { - throw new Error("request failed"); - } else { - return "response"; - } - }; - const fnValidateResponse = (result: string) => - result === "response" ? { response: "successful" } : null; - const fnTimeout = (reason: unknown) => new TimeoutError(); - const fnRequestError = (error: unknown) => - error instanceof Error ? error : null; try { - await waitForResult( - fnRequest, - fnValidateResponse, - fnTimeout, - [10, 20], - fnRequestError, - undefined, - 10 - ); + await waitForResult(fnRequest, fnValidateResponse, [10], 10); assert.fail("Expected an error to be thrown"); } catch (error) { assert(error instanceof Error, "Expected an instance of Error"); @@ -208,33 +108,4 @@ describe("waitForResult", function () { ); } }); - - it("should call lateFinish when the request takes more time than allowed", async () => { - const lateFinished = new Deferred(); - const lateFinish = () => { - lateFinished.resolve(); - }; - const fnRequest = async () => - new Promise((resolve) => - setTimeout(resolve, 20, "response") - ); - const fnValidateResponse = (result: string) => - result === "response" ? { response: "successful" } : null; - const fnTimeout = (reason: unknown) => new TimeoutError(); - try { - await waitForResult( - fnRequest, - fnValidateResponse, - fnTimeout, - [2], - undefined, - lateFinish, - 2 - ); - assert.fail("this should never happen"); - } catch (error) { - // We expect a timeout error here, so we just swallow it - } - await lateFinished.promise; - }); }); diff --git a/packages/live-share/test-for-race-conditions.js b/packages/live-share/test-for-race-conditions.js index 31bc6f453..8ddcbfd0d 100644 --- a/packages/live-share/test-for-race-conditions.js +++ b/packages/live-share/test-for-race-conditions.js @@ -2,11 +2,11 @@ * This file runs tests 50 times or until failure, and is intended to be used to find race conditions, or validate that they do not exist. */ -const execSync = require("child_process").execSync; +import { execSync } from "child_process"; for (var i = 0; i < 50; i++) { console.log("starting run:", i); - const output = execSync("npm run test", { encoding: "utf-8" }); + const output = execSync("npm run test:run", { encoding: "utf-8" }); console.log("Output was:\n", output); console.log("finished run:", i); } diff --git a/packages/live-share/tsconfig.build.json b/packages/live-share/tsconfig.build.json deleted file mode 100644 index 9d8cab4a6..000000000 --- a/packages/live-share/tsconfig.build.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ - }, - "exclude": [ - "test/**/*.ts" - ] - } \ No newline at end of file diff --git a/packages/live-share/tsconfig.json b/packages/live-share/tsconfig.json index 258994400..4e12e96eb 100644 --- a/packages/live-share/tsconfig.json +++ b/packages/live-share/tsconfig.json @@ -1,76 +1,66 @@ { - "compilerOptions": { - /* Visit https://aka.ms/tsconfig.json to read more about this file */ - - /* Basic Options */ - // "incremental": true, /* Enable incremental compilation */ - "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ - "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ - "lib": ["es2020","DOM"], /* Specify library files to be included in the compilation. */ - "allowJs": false, /* Allow javascript files to be compiled. */ - // "checkJs": true, /* Report errors in .js files. */ - // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ - "declaration": true, /* Generates corresponding '.d.ts' file. */ - "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ - "sourceMap": true, /* Generates corresponding '.map' file. */ - // "outFile": "./", /* Concatenate and emit output to single file. */ - "outDir": "./bin", /* Redirect output structure to the directory. */ - // "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ - // "composite": true, /* Enable project compilation */ - // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ - // "removeComments": true, /* Do not emit comments to output. */ - // "noEmit": true, /* Do not emit outputs. */ - // "importHelpers": true, /* Import emit helpers from 'tslib'. */ - // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ - // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ - - /* Strict Type-Checking Options */ - "strict": true, /* Enable all strict type-checking options. */ - // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* Enable strict null checks. */ - // "strictFunctionTypes": true, /* Enable strict checking of function types. */ - // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ - // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ - // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ - // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ - - /* Additional Checks */ - // "noUnusedLocals": true, /* Report errors on unused locals. */ - // "noUnusedParameters": true, /* Report errors on unused parameters. */ - // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ - // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - - /* Module Resolution Options */ - // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ - // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ - // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ - // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ - // "typeRoots": [], /* List of folders to include type definitions from. */ - // "types": [], /* Type declaration files to be included in compilation. */ - // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ - "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ - // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - - /* Source Map Options */ - // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ - // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ - - /* Experimental Options */ - // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ - // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ - - /* Advanced Options */ - "skipLibCheck": true, /* Skip type checking of declaration files. */ - "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ - }, - "exclude": ["build", "dist", "node_modules"], - "include": [ - "test/**/*.ts" - ], - "files": [ - "src/index.ts" - ] + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + /* Basic Options */ + // "incremental": true, /* Enable incremental compilation */ + "target": "ES2022" /* Specify ECMAScript target version. */, + "module": "Node16" /* Specify module code generation. */, + "lib": [ + "ES2022", + "DOM" + ] /* Specify library files to be included in the compilation. */, + "allowJs": false /* Allow javascript files to be compiled. */, + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + "declaration": true /* Generates corresponding '.d.ts' file. */, + "declarationMap": true /* Generates a sourcemap for each corresponding '.d.ts' file. */, + "sourceMap": true /* Generates corresponding '.map' file. */, + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "./bin/esm" /* Redirect output structure to the directory. */, + // "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + /* Strict Type-Checking Options */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + /* Module Resolution Options */ + // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + /* Advanced Options */ + "skipLibCheck": true /* Skip type checking of declaration files. */, + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + }, + "files": ["src/index.public.ts", "src/index.internal.ts"] } diff --git a/packages/live-share/tsconfig.test.json b/packages/live-share/tsconfig.test.json new file mode 100644 index 000000000..398bdec25 --- /dev/null +++ b/packages/live-share/tsconfig.test.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./bin/test", + "types": ["mocha", "node"] + }, + "files": [], + "include": ["src/**/*"], + "exclude": [] +} diff --git a/packages/live-share/typedoc.json b/packages/live-share/typedoc.json deleted file mode 100644 index 61a58af41..000000000 --- a/packages/live-share/typedoc.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "entryPoints": ["./src/index.ts"], - "excludeExternals": true, - "excludePrivate": true, - "excludeInternal": true, - "name": "_microsoft_live_share", - "validation": { - "invalidLink": true - } -} diff --git a/packages/updateDependencies.js b/packages/updateDependencies.js deleted file mode 100644 index d5f620b17..000000000 --- a/packages/updateDependencies.js +++ /dev/null @@ -1,99 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. - */ - -const fs = require("fs"); -const path = require("path"); -const { exit } = require("process"); - -//================================================================================================= -// CLI for programmatically setting the version number and dependencies of all packages before -// publishing. Also used to create links for local development. -// -// LOCAL DEVELOPMENT: -// -// node updateDependencies.js -// -// PUBLISHING: -// -// node updateDependencies.js 1.0.0 -// -//================================================================================================= - -const localDependencies = { - "./live-share": {}, - "./live-share-media": { - "@microsoft/live-share": "${version}:../live-share", - }, -}; - -const publishDependencies = { - "./live-share": {}, - "./live-share-media": { - "@microsoft/live-share": "${version}", - }, -}; - -const npmrcContent = - `registry=https://domoreexp.pkgs.visualstudio.com/_packaging/npm-mirror/npm/registry/` + - `\n\n` + - `always-auth=true`; - -// Grab command line args -let args = process.argv.slice(2); -if (!args || args.length == 0) { - args = ["link"]; -} else if (args.length === 1) { - if (args[0] == "npm") { - args = ["file"]; - } -} -const version = args[0]; -const isLocal = ["link", "file"].includes(args[0]); - -// Validate args and notify user -if (isLocal) { - console.log(`Configuring packages for local building and development...`); -} else if (/^\d+\.\d+\.\d+(|\-.*)$/.test(version)) { - console.log(`Configuring packages as version '${version}' for publishing...`); -} else { - console.error(`Invalid argument of '${version}'. Pass in a valid version number like '1.0.1' or '1.0.1-preview'`); - exit(); -} - -// Update packages -const dependencies = isLocal ? localDependencies : publishDependencies; -for (const package in dependencies) { - // Read package.json file - let pjson = JSON.parse(fs.readFileSync(path.resolve(package, "package.json"), "utf-8")); - - // Update package version - if (!isLocal) { - pjson.version = version; - } - - // Update dependencies - for (const entry in dependencies[package]) { - let link = dependencies[package][entry].replace("${version}", version); - pjson.dependencies[entry] = link; - } - - // Save out file - fs.writeFileSync(path.resolve(package, "package.json"), JSON.stringify(pjson, null, 4)); - fs.writeFileSync(path.resolve("", ".npmrc"), npmrcContent); - if (!isLocal) { - fs.writeFileSync(path.resolve(package, ".npmrc"), npmrcContent); - } else if (version == "file") { - fs.unlink(path.resolve(package, "yarn.lock"), (err) => { - if (!err) { - console.log("Deleted yarn.lock file"); - } - }); - fs.unlink(path.resolve(package, ".npmrc"), (err) => { - if (!err) { - console.log("Deleted .npmrc file"); - } - }); - } -} diff --git a/samples/javascript/01.dice-roller/README.md b/samples/javascript/01.dice-roller/README.md index 9aac863fc..0ead2f39f 100644 --- a/samples/javascript/01.dice-roller/README.md +++ b/samples/javascript/01.dice-roller/README.md @@ -13,15 +13,11 @@ After cloning the repository, you must first set up the npm workspace from the r ```bash npm install -npm run build:packages # Build Live Share packages cd samples/j*/01* -npm start ``` Running `npm start`, it will do two things: start the `tinylicious` server and start the application using `vite`. If you have never used `tinylicious` before, you should see instead is a prompt saying `Ok to proceed? (y)`, after which you should type `y` and press the "enter" key. In rare cases you might not see the `Ok to proceed? (y)` prompt, in which case try running `npx tinylicious@latest` in your command line directly, and then try again. -_Note:_ Do not run `npm start` before running `npm run build:packages` from the root of the project, unless you first move the sample out of this npm workspace. When using our samples, you are testing the packages using symlinks, and not the Live Share SDK versions published to npm. - ## Testing the app in Teams ### Create a ngrok tunnel to allow Teams to reach your tab app diff --git a/samples/javascript/01.dice-roller/SECURITY.md b/samples/javascript/01.dice-roller/SECURITY.md index f7b89984f..105419313 100644 --- a/samples/javascript/01.dice-roller/SECURITY.md +++ b/samples/javascript/01.dice-roller/SECURITY.md @@ -4,7 +4,7 @@ Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). -If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below. +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](), please report it to us as described below. ## Reporting Security Issues @@ -12,19 +12,19 @@ If you believe you have found a security vulnerability in any Microsoft-owned re Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). -If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). -You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: - * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) - * Full paths of source file(s) related to the manifestation of the issue - * The location of the affected source code (tag/branch/commit or direct URL) - * Any special configuration required to reproduce the issue - * Step-by-step instructions to reproduce the issue - * Proof-of-concept or exploit code (if possible) - * Impact of the issue, including how an attacker might exploit the issue +- Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) +- Full paths of source file(s) related to the manifestation of the issue +- The location of the affected source code (tag/branch/commit or direct URL) +- Any special configuration required to reproduce the issue +- Step-by-step instructions to reproduce the issue +- Proof-of-concept or exploit code (if possible) +- Impact of the issue, including how an attacker might exploit the issue This information will help us triage your report more quickly. @@ -38,4 +38,4 @@ We prefer all communications to be in English. Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). - \ No newline at end of file + diff --git a/samples/javascript/01.dice-roller/azure-pipelines.yml b/samples/javascript/01.dice-roller/azure-pipelines.yml index 411742198..094e7ea06 100644 --- a/samples/javascript/01.dice-roller/azure-pipelines.yml +++ b/samples/javascript/01.dice-roller/azure-pipelines.yml @@ -4,27 +4,27 @@ # FluidHelloWorld build for CI pr: -- main + - main -pool: 'Lite' +pool: "Lite" steps: -- task: ComponentGovernanceComponentDetection@0 - inputs: - scanType: 'Register' - verbosity: 'Verbose' - alertWarningLevel: 'High' -- task: UseNode@1 - displayName: Use Node 12.x - inputs: - version: 12.x -- task: Npm@1 - displayName: Install - inputs: - command: 'custom' - customCommand: 'install' -- task: Npm@1 - displayName: Build - inputs: - command: 'custom' - customCommand: 'run build' + - task: ComponentGovernanceComponentDetection@0 + inputs: + scanType: "Register" + verbosity: "Verbose" + alertWarningLevel: "High" + - task: UseNode@1 + displayName: Use Node 12.x + inputs: + version: 12.x + - task: Npm@1 + displayName: Install + inputs: + command: "custom" + customCommand: "install" + - task: Npm@1 + displayName: Build + inputs: + command: "custom" + customCommand: "run build" diff --git a/samples/javascript/01.dice-roller/package.json b/samples/javascript/01.dice-roller/package.json index 0e441a748..7fd92be71 100644 --- a/samples/javascript/01.dice-roller/package.json +++ b/samples/javascript/01.dice-roller/package.json @@ -14,21 +14,20 @@ "start:server": "npx tinylicious@latest", "start-https": "start-server-and-test start:server 7070 start:https", "start": "start-server-and-test start:server 7070 start:client", - "doctor": "eslint src/**/*.{j,t}s{,x} --fix --no-error-on-unmatched-pattern", - "postinstall":"node ../../../ensure-packages-built.js" + "doctor": "eslint src/**/*.{j,t}s{,x} --fix --no-error-on-unmatched-pattern" }, "dependencies": { - "@fluidframework/azure-client": "^1.1.1", - "@microsoft/live-share": "1.4.0", + "@fluidframework/azure-client": ">=2.40 <2.120", + "@microsoft/live-share": "2.0.0-internal.18", "@microsoft/teams-js": "^2.16.0", - "fluid-framework": "^1.3.6" + "fluid-framework": ">=2.40 <2.120" }, "devDependencies": { - "@fluidframework/test-client-utils": "^1.3.6", - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.7", + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", "buffer": "^6.0.3", "start-server-and-test": "^2.0.0", - "vite": "^4.0.4" + "vite": "^6.1.7" } } diff --git a/samples/javascript/01.dice-roller/src/app.js b/samples/javascript/01.dice-roller/src/app.js index b6c667c5c..38f84cdd8 100644 --- a/samples/javascript/01.dice-roller/src/app.js +++ b/samples/javascript/01.dice-roller/src/app.js @@ -3,35 +3,20 @@ * Licensed under the MIT License. */ -import { - LivePresence, - LiveShareClient, - LiveState, - TestLiveShareHost, -} from "@microsoft/live-share"; +import { LiveShareClient, TestLiveShareHost } from "@microsoft/live-share"; import { app, LiveShareHost } from "@microsoft/teams-js"; import { renderMeetingStage } from "./renderMeetingStage"; import { renderMeetingSidePanel } from "./renderMeetingSidePanel"; import { renderTabConfig } from "./renderTabConfig"; import { renderError } from "./renderError"; -import { SharedMap } from "fluid-framework"; +import { getInsecureTokenProvider } from "./insecureTokenProvider"; const searchParams = new URL(window.location.href).searchParams; const IN_TEAMS = searchParams.get("inTeams") === "1"; const root = document.getElementById("content"); let theme = "light"; -// Define container schema -const containerSchema = { - initialObjects: { - diceState: LiveState, // shared dice value, resets once all users close app - presence: LivePresence, // each user has their own dice value, resets once all users close app - storedDiceMap: SharedMap, // stored dice value that will last 6 hours from session creation - }, -}; - // STARTUP LOGIC - async function start() { // Check for page to display let view = searchParams.get("view") || "stage"; @@ -51,8 +36,8 @@ async function start() { // Load the requested view switch (view) { case "content": { - const { container } = await joinContainer(); - await renderMeetingSidePanel(container, root, theme); + const client = await getClient(); + await renderMeetingSidePanel(client, root, theme); break; } case "config": { @@ -61,22 +46,26 @@ async function start() { } case "stage": default: { - const { container } = await joinContainer(); - await renderMeetingStage(container, root, theme); + const client = await getClient(); + await renderMeetingStage(client, root, theme); break; } } } -async function joinContainer() { +async function getClient() { // Are we running in teams? - const host = IN_TEAMS ? LiveShareHost.create() : TestLiveShareHost.create(); + const host = IN_TEAMS + ? LiveShareHost.create() + : TestLiveShareHost.create(getInsecureTokenProvider()); // Create client const client = new LiveShareClient(host); // Join container - return await client.joinContainer(containerSchema); + await client.join(); + + return client; } start().catch((error) => renderError(root, error, theme)); diff --git a/samples/javascript/01.dice-roller/src/index.html b/samples/javascript/01.dice-roller/src/index.html index d2bfd415e..00bfe724e 100644 --- a/samples/javascript/01.dice-roller/src/index.html +++ b/samples/javascript/01.dice-roller/src/index.html @@ -1,7 +1,7 @@ - + @@ -13,8 +13,8 @@ Live Share - Dice Roller - +
        - \ No newline at end of file + diff --git a/samples/javascript/01.dice-roller/src/insecureTokenProvider.js b/samples/javascript/01.dice-roller/src/insecureTokenProvider.js new file mode 100644 index 000000000..29806de5f --- /dev/null +++ b/samples/javascript/01.dice-roller/src/insecureTokenProvider.js @@ -0,0 +1,21 @@ +import { InsecureTokenProvider } from "@fluidframework/test-runtime-utils/internal"; +import { v4 as uuid } from "uuid"; + +export function getInsecureTokenProvider() { + const userId = () => { + try { + const userIdParam = new URL( + window.location.href + )?.searchParams?.get("userId"); + return userIdParam; + } catch { + // window not available + return undefined; + } + }; + const tokenProvider = new InsecureTokenProvider("", { + id: userId() ?? uuid(), + name: "Test User", + }); + return tokenProvider; +} diff --git a/samples/javascript/01.dice-roller/src/renderMeetingSidePanel.js b/samples/javascript/01.dice-roller/src/renderMeetingSidePanel.js index b93c612aa..519534b97 100644 --- a/samples/javascript/01.dice-roller/src/renderMeetingSidePanel.js +++ b/samples/javascript/01.dice-roller/src/renderMeetingSidePanel.js @@ -7,7 +7,7 @@ import { meeting } from "@microsoft/teams-js"; import { getRandomDiceValue, stylizeDiceElem } from "./utils"; export async function renderMeetingSidePanel(container, elem, theme) { - const { storedDiceMap } = container.initialObjects; + const storedDiceMap = await client.getDDS("storedDice", SharedMap); const sideBarTemplate = document.createElement("template"); sideBarTemplate["innerHTML"] = `
        diff --git a/samples/javascript/01.dice-roller/src/renderMeetingStage.js b/samples/javascript/01.dice-roller/src/renderMeetingStage.js index 8e89681fb..c7e6fe744 100644 --- a/samples/javascript/01.dice-roller/src/renderMeetingStage.js +++ b/samples/javascript/01.dice-roller/src/renderMeetingStage.js @@ -3,10 +3,15 @@ * Licensed under the MIT License. */ -import { PresenceState, UserMeetingRole } from "@microsoft/live-share"; +import { + PresenceStatus, + UserMeetingRole, + LivePresence, + LiveState, +} from "@microsoft/live-share"; import { getRandomDiceValue, stylizeDiceElem } from "./utils"; -export async function renderMeetingStage(container, elem, theme) { +export async function renderMeetingStage(client, elem, theme) { const stageTemplate = document.createElement("template"); stageTemplate["innerHTML"] = `
        @@ -17,7 +22,8 @@ export async function renderMeetingStage(container, elem, theme) {

        Users:

        `; - const { diceState, presence } = container.initialObjects; + const diceState = await client.getDDS("dice", LiveState); + const presence = await client.getDDS("dice", LivePresence); elem.appendChild(stageTemplate.content.cloneNode(true)); const wrapperElem = elem.querySelector(".wrapper"); @@ -73,8 +79,8 @@ async function renderPresenceDiceList(presence, wrapperElem) { async function renderUserDice(presence, userPresence, local, wrapperElem) { const userDiceElementId = `user-dice-${userPresence.userId}`; let userDiceElement = document.getElementById(userDiceElementId); - // If the user's state is not offline, remove it from the DOM - if (userPresence.state !== PresenceState.online) { + // If the user's status is not offline, remove it from the DOM + if (userPresence.status !== PresenceStatus.online) { userDiceElement?.remove(); return; } diff --git a/samples/javascript/01.dice-roller/src/styles.css b/samples/javascript/01.dice-roller/src/styles.css index faa20f511..9072421d2 100644 --- a/samples/javascript/01.dice-roller/src/styles.css +++ b/samples/javascript/01.dice-roller/src/styles.css @@ -2,7 +2,7 @@ text-align: center; max-height: 100vh; overflow-y: none; - font-family: "Segoe UI" + font-family: "Segoe UI"; } .wrapper.light { color: black; diff --git a/samples/javascript/02.react-video/README.md b/samples/javascript/02.react-video/README.md index 2bf380647..0643f84c5 100644 --- a/samples/javascript/02.react-video/README.md +++ b/samples/javascript/02.react-video/README.md @@ -8,12 +8,9 @@ After cloning the repository, you must first set up the npm workspace from the r ```bash npm install -npm run build:packages # Build Live Share packages cd samples/j*/02* ``` -_Note:_ Do not run `npm start` before running `npm run build:packages` from the root of the project, unless you first move the sample out of this npm workspace. When using our samples, you are testing the packages using symlinks, and not the Live Share SDK versions published to npm. - ## Testing locally in browser ### `npm run start` diff --git a/samples/javascript/02.react-video/__tests__/test1.js b/samples/javascript/02.react-video/__tests__/test1.js index 3947cee86..5b87e982f 100644 --- a/samples/javascript/02.react-video/__tests__/test1.js +++ b/samples/javascript/02.react-video/__tests__/test1.js @@ -2,9 +2,13 @@ const timeout = 4 * 60 * 1000; // adjust this time out as per number of windows const chalk = require("chalk"); // functions to test for a particular player event -const isPlay = (log) => log && log.indexOf("MediaPlayerSynchronizer:SeekingPlayerToStartPosition") != -1; -const isPause = (log) => log && log.indexOf("MediaPlayerSynchronizer:PauseAction") != -1; -const isSeek = (log) => log && log.indexOf("MediaPlayerSynchronizer:SeekToAction") != -1; +const isPlay = (log) => + log && + log.indexOf("MediaPlayerSynchronizer:SeekingPlayerToStartPosition") != -1; +const isPause = (log) => + log && log.indexOf("MediaPlayerSynchronizer:PauseAction") != -1; +const isSeek = (log) => + log && log.indexOf("MediaPlayerSynchronizer:SeekToAction") != -1; const isSeekTo = (log, position) => { const positionStr = `"position":${position}`; @@ -245,7 +249,8 @@ const installMouseHelper = async (page) => { true ); function updateButtons(buttons) { - for (let i = 0; i < 5; i++) box.classList.toggle("button-" + i, buttons & (1 << i)); + for (let i = 0; i < 5; i++) + box.classList.toggle("button-" + i, buttons & (1 << i)); } }, false diff --git a/samples/javascript/02.react-video/index.html b/samples/javascript/02.react-video/index.html index 4a4cf632b..4783a612e 100644 --- a/samples/javascript/02.react-video/index.html +++ b/samples/javascript/02.react-video/index.html @@ -1,4 +1,4 @@ - + diff --git a/samples/javascript/02.react-video/package.json b/samples/javascript/02.react-video/package.json index 77a856c7e..5734a7789 100644 --- a/samples/javascript/02.react-video/package.json +++ b/samples/javascript/02.react-video/package.json @@ -1,72 +1,70 @@ { - "name": "react-video", - "private": true, - "version": "1.0.0", - "description": "Sample video app using react.", - "repository": "https://github.com/microsoft/live-share-sdk", - "license": "Microsoft", - "author": "Microsoft", - "dependencies": { - "@fluentui/react-components": "^9.18.6", - "@fluentui/react-icons": "^2.0.202", - "@fluentui/react-theme": "^9.1.5", - "@fluidframework/azure-client": "^1.1.1", - "@microsoft/live-share": "1.4.0", - "@microsoft/live-share-media": "1.4.0", - "@microsoft/teams-js": "^2.16.0", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^13.4.0", - "@testing-library/user-event": "^14.4.3", - "fluid-framework": "^1.3.6", - "lodash": "^4.17.21", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-router": "^6.4.2", - "react-router-dom": "^6.4.2", - "use-resize-observer": "^9.1.0", - "uuid": "^9.0.0", - "web-vitals": "^3.1.1" - }, - "devDependencies": { - "@fluidframework/test-client-utils": "^1.3.6", - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.7", - "@vitejs/plugin-react": "^3.0.1", - "chalk": "^5.2.0", - "eslint": "^8.41.0", - "eslint-config-prettier": "^8.8.0", - "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-react": "^7.32.2", - "jest-puppeteer": "^6.1.0", - "prettier": "^2.8.8", - "puppeteer": "^20.1.0", - "rimraf": "^2.6.3", - "start-server-and-test": "^2.0.0", - "vite": "^4.0.4" - }, - "scripts": { - "build": "vite build", - "clean": "npx shx rm -rf build", - "doctor": "eslint src/**/*.{j,t}s{,x} --fix --no-error-on-unmatched-pattern", - "start": "start-server-and-test start:server 7070 start:client", - "start-https": "start-server-and-test start:server 7070 start:https", - "start:client": "vite", - "start:server": "npx tinylicious@latest", - "start:https": "vite --config vite.https-config.js", - "test": "jest", - "preview": "vite preview", - "postinstall":"node ../../../ensure-packages-built.js" - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - } + "name": "react-video", + "private": true, + "version": "1.0.0", + "description": "Sample video app using react.", + "repository": "https://github.com/microsoft/live-share-sdk", + "license": "Microsoft", + "author": "Microsoft", + "dependencies": { + "@fluentui/react-components": "^9.18.6", + "@fluentui/react-icons": "^2.0.202", + "@fluentui/react-theme": "^9.1.5", + "@fluidframework/azure-client": ">=2.40 <2.120", + "@microsoft/live-share": "2.0.0-internal.18", + "@microsoft/live-share-media": "2.0.0-internal.18", + "@microsoft/teams-js": "^2.16.0", + "@testing-library/jest-dom": "^5.16.5", + "@testing-library/react": "^13.4.0", + "@testing-library/user-event": "^14.4.3", + "fluid-framework": ">=2.40 <2.120", + "lodash": "^4.17.21", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router": "^6.4.2", + "react-router-dom": "^6.4.2", + "use-resize-observer": "^9.1.0", + "uuid": "^9.0.0", + "web-vitals": "^3.1.1" + }, + "devDependencies": { + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "@vitejs/plugin-react": "^5.1.4", + "chalk": "^5.2.0", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-react": "^7.34.4", + "jest-puppeteer": "^11.0.0", + "prettier": "^3.3.3", + "puppeteer": "^24.34.0", + "rimraf": "^2.6.3", + "start-server-and-test": "^2.0.0", + "vite": "^6.1.7" + }, + "scripts": { + "build": "vite build", + "clean": "npx shx rm -rf build", + "doctor": "eslint src/**/*.{j,t}s{,x} --fix --no-error-on-unmatched-pattern", + "start": "start-server-and-test start:server 7070 start:client", + "start-https": "start-server-and-test start:server 7070 start:https", + "start:client": "vite", + "start:server": "npx tinylicious@latest", + "start:https": "vite --config vite.https-config.js", + "test": "jest", + "preview": "vite preview" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } } diff --git a/samples/javascript/02.react-video/public/manifest.json b/samples/javascript/02.react-video/public/manifest.json index 080d6c77a..f01493ff0 100644 --- a/samples/javascript/02.react-video/public/manifest.json +++ b/samples/javascript/02.react-video/public/manifest.json @@ -1,25 +1,25 @@ { - "short_name": "React App", - "name": "Create React App Sample", - "icons": [ - { - "src": "favicon.ico", - "sizes": "64x64 32x32 24x24 16x16", - "type": "image/x-icon" - }, - { - "src": "logo192.png", - "type": "image/png", - "sizes": "192x192" - }, - { - "src": "logo512.png", - "type": "image/png", - "sizes": "512x512" - } - ], - "start_url": ".", - "display": "standalone", - "theme_color": "#000000", - "background_color": "#ffffff" + "short_name": "React App", + "name": "Create React App Sample", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + }, + { + "src": "logo192.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "logo512.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" } diff --git a/samples/javascript/02.react-video/puppeteer_environment.js b/samples/javascript/02.react-video/puppeteer_environment.js index b94946c90..9e408fb85 100644 --- a/samples/javascript/02.react-video/puppeteer_environment.js +++ b/samples/javascript/02.react-video/puppeteer_environment.js @@ -15,7 +15,10 @@ class PuppeteerEnvironment extends NodeEnvironment { async setup() { console.log(chalk.yellow("Setup Test Environment.")); await super.setup(); - const wsEndpoint = fs.readFileSync(path.join(DIR, "wsEndpoint"), "utf8"); + const wsEndpoint = fs.readFileSync( + path.join(DIR, "wsEndpoint"), + "utf8" + ); if (!wsEndpoint) { throw new Error("wsEndpoint not found"); } diff --git a/samples/javascript/02.react-video/setup.js b/samples/javascript/02.react-video/setup.js index 7c426c69b..3046d1cdf 100644 --- a/samples/javascript/02.react-video/setup.js +++ b/samples/javascript/02.react-video/setup.js @@ -11,7 +11,8 @@ module.exports = async function () { console.log(chalk.green("Setup Puppeteer")); const browser = await puppeteer.launch({ headless: false, - executablePath: "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe", + executablePath: + "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe", // if you are an OS user, please use "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" }); // This global is not available inside tests but only in global teardown diff --git a/samples/javascript/02.react-video/src/App.jsx b/samples/javascript/02.react-video/src/App.jsx index 756bd70d8..d4c82304d 100644 --- a/samples/javascript/02.react-video/src/App.jsx +++ b/samples/javascript/02.react-video/src/App.jsx @@ -59,17 +59,17 @@ export default function App() { break; } }); - microsoftTeams.app.registerOnThemeChangeHandler(function ( - theme - ) { - if (theme == "dark") { - setTeamsTheme(teamsDarkTheme); - } else if (theme == "contrast") { - setTeamsTheme(teamsHighContrastTheme); - } else { - setTeamsTheme(teamsLightTheme); + microsoftTeams.app.registerOnThemeChangeHandler( + function (theme) { + if (theme == "dark") { + setTeamsTheme(teamsDarkTheme); + } else if (theme == "contrast") { + setTeamsTheme(teamsHighContrastTheme); + } else { + setTeamsTheme(teamsLightTheme); + } } - }); + ); } else { setInitialized(true); } diff --git a/samples/javascript/02.react-video/src/components/MediaPlayerContainer.jsx b/samples/javascript/02.react-video/src/components/MediaPlayerContainer.jsx index bc79a8f51..981514e6e 100644 --- a/samples/javascript/02.react-video/src/components/MediaPlayerContainer.jsx +++ b/samples/javascript/02.react-video/src/components/MediaPlayerContainer.jsx @@ -55,7 +55,7 @@ export const MediaPlayerContainer = ({ setShowControls(false); }, [setShowControls]); // eslint-disable-next-line - const debouncedHideControls = useCallback(debounce(hideControls, 2500), [ + const debouncedHideControls = useCallback(debounce(hideControls, 2500), [ hideControls, ]); diff --git a/samples/javascript/02.react-video/src/components/PlayerProgressBar.jsx b/samples/javascript/02.react-video/src/components/PlayerProgressBar.jsx index 57897d327..0d744e7d8 100644 --- a/samples/javascript/02.react-video/src/components/PlayerProgressBar.jsx +++ b/samples/javascript/02.react-video/src/components/PlayerProgressBar.jsx @@ -38,7 +38,7 @@ const PlayerProgressBar = ({ }, [onSeek, setIsSeeking, localCurrentTime]); // eslint-disable-next-line - const debouncedSeek = useCallback(debounce(onDidSeek, 200), [ + const debouncedSeek = useCallback(debounce(onDidSeek, 200), [ onDidSeek, localCurrentTime, ]); diff --git a/samples/javascript/02.react-video/src/index.css b/samples/javascript/02.react-video/src/index.css index ec2585e8c..a2fefc9cc 100644 --- a/samples/javascript/02.react-video/src/index.css +++ b/samples/javascript/02.react-video/src/index.css @@ -1,13 +1,14 @@ body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + margin: 0; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", + "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; + font-family: + source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } diff --git a/samples/javascript/02.react-video/src/pages/MeetingStage.jsx b/samples/javascript/02.react-video/src/pages/MeetingStage.jsx index e9cdfe4c3..a2fd2dee5 100644 --- a/samples/javascript/02.react-video/src/pages/MeetingStage.jsx +++ b/samples/javascript/02.react-video/src/pages/MeetingStage.jsx @@ -15,6 +15,7 @@ import { LiveShareClient, TestLiveShareHost } from "@microsoft/live-share"; import { inTeams } from "../utils/inTeams"; import { ConsoleLogger } from "./ConsoleLogger"; import { LiveShareHost } from "@microsoft/teams-js"; +import { getInsecureTokenProvider } from "../utils/insecureTokenProvider"; const MeetingStage = () => { // Started initializing flag @@ -53,7 +54,7 @@ const MeetingStage = () => { // Are we in teams? const host = inTeams() ? LiveShareHost.create() - : TestLiveShareHost.create(); + : TestLiveShareHost.create(getInsecureTokenProvider()); // Define Fluid document schema and create container const client = new LiveShareClient(host, { @@ -62,7 +63,7 @@ const MeetingStage = () => { const schema = { initialObjects: { mediaSession: LiveMediaSession }, }; - const { container } = await client.joinContainer(schema); + const { container } = await client.join(schema); const { mediaSession } = container.initialObjects; synchronizer.current = mediaSession.synchronize( videoElement.current diff --git a/samples/javascript/02.react-video/src/utils/insecureTokenProvider.js b/samples/javascript/02.react-video/src/utils/insecureTokenProvider.js new file mode 100644 index 000000000..29806de5f --- /dev/null +++ b/samples/javascript/02.react-video/src/utils/insecureTokenProvider.js @@ -0,0 +1,21 @@ +import { InsecureTokenProvider } from "@fluidframework/test-runtime-utils/internal"; +import { v4 as uuid } from "uuid"; + +export function getInsecureTokenProvider() { + const userId = () => { + try { + const userIdParam = new URL( + window.location.href + )?.searchParams?.get("userId"); + return userIdParam; + } catch { + // window not available + return undefined; + } + }; + const tokenProvider = new InsecureTokenProvider("", { + id: userId() ?? uuid(), + name: "Test User", + }); + return tokenProvider; +} diff --git a/samples/javascript/03.live-canvas-demo/README.md b/samples/javascript/03.live-canvas-demo/README.md index 51583e1cd..cc8c96a5d 100644 --- a/samples/javascript/03.live-canvas-demo/README.md +++ b/samples/javascript/03.live-canvas-demo/README.md @@ -8,12 +8,9 @@ After cloning the repository, you must first set up the npm workspace from the r ```bash npm install -npm run build:packages # Build Live Share packages cd samples/j*/03* ``` -_Note:_ Do not run `npm start` before running `npm run build:packages` from the root of the project, unless you first move the sample out of this npm workspace. When using our samples, you are testing the packages using symlinks, and not the Live Share SDK versions published to npm. - ## Testing locally in browser ### `npm run start` diff --git a/samples/javascript/03.live-canvas-demo/package.json b/samples/javascript/03.live-canvas-demo/package.json index 33a66bca8..c0900eb27 100644 --- a/samples/javascript/03.live-canvas-demo/package.json +++ b/samples/javascript/03.live-canvas-demo/package.json @@ -13,22 +13,21 @@ "start:client": "vite", "start:https": "vite --config vite.https-config.js", "start:server": "npx tinylicious@latest", - "doctor": "eslint src/**/*.{j,t}s{,x} --fix --no-error-on-unmatched-pattern", - "postinstall":"node ../../../ensure-packages-built.js" + "doctor": "eslint src/**/*.{j,t}s{,x} --fix --no-error-on-unmatched-pattern" }, "dependencies": { - "@fluidframework/azure-client": "^1.1.1", - "@microsoft/live-share": "1.4.0", - "@microsoft/live-share-canvas": "1.4.0", + "@fluidframework/azure-client": ">=2.40 <2.120", + "@microsoft/live-share": "2.0.0-internal.18", + "@microsoft/live-share-canvas": "2.0.0-internal.18", "@microsoft/teams-js": "^2.16.0", - "fluid-framework": "^1.3.6" + "fluid-framework": ">=2.40 <2.120" }, "devDependencies": { - "@fluidframework/test-client-utils": "^1.3.6", - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.7", + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", "buffer": "^6.0.3", "start-server-and-test": "^2.0.0", - "vite": "^4.0.4" + "vite": "^6.1.7" } } diff --git a/samples/javascript/03.live-canvas-demo/src/app.css b/samples/javascript/03.live-canvas-demo/src/app.css index 80a929bcb..2b0ec2626 100644 --- a/samples/javascript/03.live-canvas-demo/src/app.css +++ b/samples/javascript/03.live-canvas-demo/src/app.css @@ -1,6 +1,6 @@ * { box-sizing: border-box; - font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; } body { @@ -19,7 +19,16 @@ body { flex: 1 1 100%; position: relative; overflow: hidden; - background-image: linear-gradient(#444cf7 0.6000000000000001px, transparent 0.6000000000000001px), linear-gradient(to right, #444cf7 0.6000000000000001px, transparent 0.6000000000000001px); + background-image: + linear-gradient( + #444cf7 0.6000000000000001px, + transparent 0.6000000000000001px + ), + linear-gradient( + to right, + #444cf7 0.6000000000000001px, + transparent 0.6000000000000001px + ); background-size: 12px 12px; } @@ -51,21 +60,21 @@ body { font-weight: 600; padding: 2px 10px 3px 10px; -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - background-color: #EEEEEE; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-color: #eeeeee; color: black; border: 1px solid #888888; border-radius: 2px; } .toolbar > button:hover { - background-color: #DDDDDD; + background-color: #dddddd; border: 1px solid #777777; } .toolbar > button:active { - background-color: #CCCCCC; + background-color: #cccccc; border: 1px solid #777777; -} \ No newline at end of file +} diff --git a/samples/javascript/03.live-canvas-demo/src/index.html b/samples/javascript/03.live-canvas-demo/src/index.html index 86a59d838..d510e2caa 100644 --- a/samples/javascript/03.live-canvas-demo/src/index.html +++ b/samples/javascript/03.live-canvas-demo/src/index.html @@ -1,4 +1,4 @@ - + diff --git a/samples/javascript/03.live-canvas-demo/src/insecureTokenProvider.js b/samples/javascript/03.live-canvas-demo/src/insecureTokenProvider.js new file mode 100644 index 000000000..29806de5f --- /dev/null +++ b/samples/javascript/03.live-canvas-demo/src/insecureTokenProvider.js @@ -0,0 +1,21 @@ +import { InsecureTokenProvider } from "@fluidframework/test-runtime-utils/internal"; +import { v4 as uuid } from "uuid"; + +export function getInsecureTokenProvider() { + const userId = () => { + try { + const userIdParam = new URL( + window.location.href + )?.searchParams?.get("userId"); + return userIdParam; + } catch { + // window not available + return undefined; + } + }; + const tokenProvider = new InsecureTokenProvider("", { + id: userId() ?? uuid(), + name: "Test User", + }); + return tokenProvider; +} diff --git a/samples/javascript/03.live-canvas-demo/src/stage-view.js b/samples/javascript/03.live-canvas-demo/src/stage-view.js index 1ba00be38..97ab65352 100644 --- a/samples/javascript/03.live-canvas-demo/src/stage-view.js +++ b/samples/javascript/03.live-canvas-demo/src/stage-view.js @@ -12,6 +12,7 @@ import { } from "@microsoft/live-share-canvas"; import * as Utils from "./utils"; import { View } from "./view"; +import { getInsecureTokenProvider } from "./insecureTokenProvider"; /** * Other images @@ -59,15 +60,9 @@ const appTemplate = `
        `; -const containerSchema = { - initialObjects: { - liveCanvas: LiveCanvas, - }, -}; - export class StageView extends View { _inkingManager; - _container; + _client; offsetBy(x, y) { this._inkingManager.offset = { @@ -78,8 +73,8 @@ export class StageView extends View { this.updateBackgroundImagePosition(); } - getLiveCanvas() { - return this._container.initialObjects.liveCanvas; + async getLiveCanvas() { + return await this._client.getDDS("liveCanvas", LiveCanvas); } _hostResizeObserver; @@ -87,17 +82,15 @@ export class StageView extends View { async internalStart() { const host = Utils.runningInTeams() ? Teams.LiveShareHost.create() - : TestLiveShareHost.create(); + : TestLiveShareHost.create(getInsecureTokenProvider()); const client = new LiveShareClient(host); - - this._container = ( - await client.joinContainer(containerSchema) - ).container; + await client.join(); + this._client = client; const inkingHost = document.getElementById("inkingHost"); if (inkingHost) { - const liveCanvas = this.getLiveCanvas(); + const liveCanvas = await this.getLiveCanvas(); this._inkingManager = new InkingManager(inkingHost); @@ -262,8 +255,8 @@ export class StageView extends View { this.updateBackgroundImagePosition(); }); - setupButton("btnToggleCursorShare", () => { - const liveCanvas = this.getLiveCanvas(); + setupButton("btnToggleCursorShare", async () => { + const liveCanvas = await this.getLiveCanvas(); const isCursorShared = liveCanvas.isCursorShared; liveCanvas.isCursorShared = !isCursorShared; diff --git a/samples/javascript/04.live-share-react/README.md b/samples/javascript/04.live-share-react/README.md index 8d32c18a0..c9dd2949e 100644 --- a/samples/javascript/04.live-share-react/README.md +++ b/samples/javascript/04.live-share-react/README.md @@ -10,12 +10,9 @@ After cloning the repository, you must first set up the npm workspace from the r ```bash npm install -npm run build:packages # Build Live Share packages cd samples/j*/04* ``` -_Note:_ Do not run `npm start` before running `npm run build:packages` from the root of the project, unless you first move the sample out of this npm workspace. When using our samples, you are testing the packages using symlinks, and not the Live Share SDK versions published to npm. - ## Testing locally in browser ### `npm run start` diff --git a/samples/javascript/04.live-share-react/index.html b/samples/javascript/04.live-share-react/index.html index a242a5c6f..5845f54e6 100644 --- a/samples/javascript/04.live-share-react/index.html +++ b/samples/javascript/04.live-share-react/index.html @@ -1,23 +1,20 @@ - + - - - - - - - - - Live Share React Demo - - - -
        - - - + --> diff --git a/samples/javascript/04.live-share-react/package.json b/samples/javascript/04.live-share-react/package.json index e83be3349..f31d2ac5c 100644 --- a/samples/javascript/04.live-share-react/package.json +++ b/samples/javascript/04.live-share-react/package.json @@ -5,16 +5,16 @@ "author": "Microsoft", "license": "MIT", "dependencies": { + "@fluidframework/azure-client": ">=2.40 <2.120", "@fluentui/react-components": "^9.18.6", "@fluentui/react-icons": "^2.0.202", "@fluentui/react-theme": "^9.1.5", - "@fluidframework/azure-client": "^1.1.1", - "@microsoft/live-share": "1.4.0", - "@microsoft/live-share-media": "1.4.0", - "@microsoft/live-share-canvas": "1.4.0", - "@microsoft/live-share-react": "1.4.0-preview.0", + "@microsoft/live-share": "2.0.0-internal.18", + "@microsoft/live-share-media": "2.0.0-internal.18", + "@microsoft/live-share-canvas": "2.0.0-internal.18", + "@microsoft/live-share-react": "2.0.0-internal.18", "@microsoft/teams-js": "^2.16.0", - "fluid-framework": "^1.3.6", + "fluid-framework": ">=2.40 <2.120", "lodash": "^4.17.21", "prop-types": "^15.8.1", "react": "^18.2.0", @@ -26,20 +26,20 @@ "web-vitals": "^3.1.1" }, "devDependencies": { - "@fluidframework/test-client-utils": "^1.3.6", + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.4.3", - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.7", - "@vitejs/plugin-react": "^3.0.1", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "@vitejs/plugin-react": "^5.1.4", "dotenv-cli": "^7.2.1", - "eslint": "^8.41.0", - "eslint-config-prettier": "^8.8.0", - "eslint-plugin-prettier": "^4.2.1", - "prettier": "^2.8.8", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.1.3", + "prettier": "^3.3.3", "start-server-and-test": "^2.0.0", - "vite": "^4.0.4" + "vite": "^6.1.7" }, "scripts": { "build": "vite build", @@ -49,8 +49,7 @@ "start-https": "start-server-and-test start:server 7070 start:https", "start:client": "vite", "start:https": "vite --config vite.https-config.js", - "start:server": "npx tinylicious@latest", - "postinstall":"node ../../../ensure-packages-built.js" + "start:server": "npx tinylicious@latest" }, "browserslist": { "production": [ diff --git a/samples/javascript/04.live-share-react/public/manifest.json b/samples/javascript/04.live-share-react/public/manifest.json index 080d6c77a..f01493ff0 100644 --- a/samples/javascript/04.live-share-react/public/manifest.json +++ b/samples/javascript/04.live-share-react/public/manifest.json @@ -1,25 +1,25 @@ { - "short_name": "React App", - "name": "Create React App Sample", - "icons": [ - { - "src": "favicon.ico", - "sizes": "64x64 32x32 24x24 16x16", - "type": "image/x-icon" - }, - { - "src": "logo192.png", - "type": "image/png", - "sizes": "192x192" - }, - { - "src": "logo512.png", - "type": "image/png", - "sizes": "512x512" - } - ], - "start_url": ".", - "display": "standalone", - "theme_color": "#000000", - "background_color": "#ffffff" + "short_name": "React App", + "name": "Create React App Sample", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + }, + { + "src": "logo192.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "logo512.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" } diff --git a/samples/javascript/04.live-share-react/src/components/ExampleLiveCanvas.jsx b/samples/javascript/04.live-share-react/src/components/ExampleLiveCanvas.jsx index b6eb1a915..792e795a0 100644 --- a/samples/javascript/04.live-share-react/src/components/ExampleLiveCanvas.jsx +++ b/samples/javascript/04.live-share-react/src/components/ExampleLiveCanvas.jsx @@ -8,17 +8,11 @@ export const ExampleLiveCanvas = () => { const [active, setActive] = useState(true); const [tool, setTool] = useState(InkingTool.pen); const [isCursorShared, setIsCursorShared] = useState(true); - const { liveCanvas } = useLiveCanvas( - "CUSTOM-LIVE-CANVAS", - liveCanvasRef, + const { liveCanvas } = useLiveCanvas("CUSTOM-LIVE-CANVAS", liveCanvasRef, { active, tool, - undefined, - undefined, - undefined, - undefined, - isCursorShared - ); + isCursorShared, + }); return (
        diff --git a/samples/javascript/04.live-share-react/src/components/ExampleLivePresence.jsx b/samples/javascript/04.live-share-react/src/components/ExampleLivePresence.jsx index b8456a313..b23ff81f0 100644 --- a/samples/javascript/04.live-share-react/src/components/ExampleLivePresence.jsx +++ b/samples/javascript/04.live-share-react/src/components/ExampleLivePresence.jsx @@ -1,16 +1,11 @@ -import { PresenceState, UserMeetingRole } from "@microsoft/live-share"; import { useLivePresence } from "@microsoft/live-share-react"; -// You can use this as an easy way to filter out certain roles -const ALLOWED_ROLES = [UserMeetingRole.organizer, UserMeetingRole.presenter]; - export const ExampleLivePresence = () => { - const { localUser, allUsers, updatePresence } = useLivePresence( - "CUSTOM-PRESENCE-KEY", - { toggleCount: 0 }, // optional - PresenceState.online, // optional, default online - ALLOWED_ROLES // optional, default all users can set - ); + const { localUser, allUsers, updatePresence, livePresence } = + useLivePresence("CUSTOM-PRESENCE-KEY", { count: 0 }); + + if (!livePresence) return <>Loading presence...; + return (

        {"Users:"}

        @@ -19,29 +14,19 @@ export const ExampleLivePresence = () => {
        {`${user.displayName}, isLocalUser: ${user.isLocalUser}, ${user.userId}`}
        + >{`${user.displayName}, isLocalUser: ${user.isLocalUser}, count: ${user.data?.count}`}
        ))}
        ); diff --git a/samples/javascript/04.live-share-react/src/index.css b/samples/javascript/04.live-share-react/src/index.css index ef30d5250..12dc137f3 100644 --- a/samples/javascript/04.live-share-react/src/index.css +++ b/samples/javascript/04.live-share-react/src/index.css @@ -1,116 +1,116 @@ :root { - font-family: Inter, Avenir, Helvetica, Arial, sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; + font-family: Inter, Avenir, Helvetica, Arial, sans-serif; + font-size: 16px; + line-height: 24px; + font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: #242424; + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; } div { - display: block; + display: block; } a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; + font-weight: 500; + color: #646cff; + text-decoration: inherit; } a:hover { - color: #535bf2; + color: #535bf2; } body { - margin: 0; - min-height: 100vh; + margin: 0; + min-height: 100vh; } h1 { - font-size: 2.4em; - line-height: 1.1; + font-size: 2.4em; + line-height: 1.1; } h2 { - font-size: 1.2em; - line-height: 1.1; + font-size: 1.2em; + line-height: 1.1; } h3 { - font-size: 16px; + font-size: 16px; } h4 { - font-size: 0.8em; - line-height: 1.1; + font-size: 0.8em; + line-height: 1.1; } button { - border-radius: 8px; - border: 1px solid transparent; - padding: 0.6em 1.2em; - font-size: 1em; - font-weight: 500; - font-family: inherit; - background-color: #1a1a1a; - cursor: pointer; - transition: border-color 0.25s; + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; } button:hover { - border-color: #646cff; + border-color: #646cff; } button:focus, button:focus-visible { - outline: 4px auto -webkit-focus-ring-color; + outline: 4px auto -webkit-focus-ring-color; } @media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - a:hover { - color: #747bff; - } - button { - background-color: #e2e2e2; - } + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #e2e2e2; + } } .card { - padding: 16px; - margin: 8px; - border-radius: 8px; - background-color: #242424; - color: white; - display: inline-block; - width: 320px; + padding: 16px; + margin: 8px; + border-radius: 8px; + background-color: #242424; + color: white; + display: inline-block; + width: 320px; } .flex { - display: flex; + display: flex; } .flex > * { - margin-right: 8px; + margin-right: 8px; } .flex.row.hAlign { - justify-items: center; + justify-items: center; } .flex.row.vAlign { - align-items: center; + align-items: center; } .flex.wrap { - flex-wrap: wrap; + flex-wrap: wrap; } .full-width { - width: 100%; + width: 100%; } .margin-bottom { - margin-bottom: 12px; + margin-bottom: 12px; } diff --git a/samples/javascript/04.live-share-react/src/pages/AzureAutoJoin.jsx b/samples/javascript/04.live-share-react/src/pages/AzureAutoJoin.jsx index 6313a93a2..e17a7d37a 100644 --- a/samples/javascript/04.live-share-react/src/pages/AzureAutoJoin.jsx +++ b/samples/javascript/04.live-share-react/src/pages/AzureAutoJoin.jsx @@ -1,6 +1,6 @@ -import { InsecureTokenProvider } from "@fluidframework/test-client-utils"; +import { InsecureTokenProvider } from "@fluidframework/test-runtime-utils"; import { AzureProvider } from "@microsoft/live-share-react"; -import { SharedMap } from "fluid-framework"; +import { SharedMap } from "fluid-framework/legacy"; import { ExampleSharedMap, ExampleSharedState, diff --git a/samples/javascript/04.live-share-react/src/pages/LiveShareAutoJoin.jsx b/samples/javascript/04.live-share-react/src/pages/LiveShareAutoJoin.jsx index faf9fbdb4..5fb5d5b04 100644 --- a/samples/javascript/04.live-share-react/src/pages/LiveShareAutoJoin.jsx +++ b/samples/javascript/04.live-share-react/src/pages/LiveShareAutoJoin.jsx @@ -16,12 +16,15 @@ import { } from "../components"; import { inTeams } from "../utils/inTeams"; import { useRef } from "react"; +import { getInsecureTokenProvider } from "../utils/insecureTokenProvider"; const IN_TEAMS = inTeams(); export const LiveShareAutoJoin = () => { const hostRef = useRef( - IN_TEAMS ? LiveShareHost.create() : TestLiveShareHost.create() + IN_TEAMS + ? LiveShareHost.create() + : TestLiveShareHost.create(getInsecureTokenProvider()) ); return ( diff --git a/samples/javascript/04.live-share-react/src/pages/LiveShareManualJoin.jsx b/samples/javascript/04.live-share-react/src/pages/LiveShareManualJoin.jsx index b33cc262d..8069abf0c 100644 --- a/samples/javascript/04.live-share-react/src/pages/LiveShareManualJoin.jsx +++ b/samples/javascript/04.live-share-react/src/pages/LiveShareManualJoin.jsx @@ -14,12 +14,12 @@ import { ExampleMediaSynchronizer, ExampleSharedMap, ExampleSharedState, - TeamsClientLoader, } from "../components"; import { inTeams } from "../utils/inTeams"; +import { getInsecureTokenProvider } from "../utils/insecureTokenProvider"; const IN_TEAMS = inTeams(); -const testHost = TestLiveShareHost.create(); +const testHost = TestLiveShareHost.create(getInsecureTokenProvider()); // If you want to test role validation locally, you can override the roles of remote/local users. // This will only work well with a max of two clients. const url = new URL(window.location.href); diff --git a/samples/javascript/04.live-share-react/src/utils/insecureTokenProvider.js b/samples/javascript/04.live-share-react/src/utils/insecureTokenProvider.js new file mode 100644 index 000000000..9f1409741 --- /dev/null +++ b/samples/javascript/04.live-share-react/src/utils/insecureTokenProvider.js @@ -0,0 +1,22 @@ +import { ITokenProvider } from "@fluidframework/azure-client"; +import { InsecureTokenProvider } from "@fluidframework/test-runtime-utils/internal"; +import { v4 as uuid } from "uuid"; + +export function getInsecureTokenProvider() { + const userId = () => { + try { + const userIdParam = new URL( + window.location.href + )?.searchParams?.get("userId"); + return userIdParam; + } catch { + // window not available + return undefined; + } + }; + const tokenProvider = new InsecureTokenProvider("", { + id: userId() ?? uuid(), + name: "Test User", + }); + return tokenProvider; +} diff --git a/samples/javascript/05.dice-roller-turbo/README.md b/samples/javascript/05.dice-roller-turbo/README.md index 3ff045688..8defde15b 100644 --- a/samples/javascript/05.dice-roller-turbo/README.md +++ b/samples/javascript/05.dice-roller-turbo/README.md @@ -12,12 +12,9 @@ After cloning the repository, you must first set up the npm workspace from the r ```bash npm install -npm run build:packages # Build Live Share packages cd samples/j*/05* ``` -_Note:_ Do not run `npm start` before running `npm run build:packages` from the root of the project, unless you first move the sample out of this npm workspace. When using our samples, you are testing the packages using symlinks, and not the Live Share SDK versions published to npm. - ## Testing locally in browser ### `npm run start` diff --git a/samples/javascript/05.dice-roller-turbo/SECURITY.md b/samples/javascript/05.dice-roller-turbo/SECURITY.md index f7b89984f..105419313 100644 --- a/samples/javascript/05.dice-roller-turbo/SECURITY.md +++ b/samples/javascript/05.dice-roller-turbo/SECURITY.md @@ -4,7 +4,7 @@ Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). -If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below. +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](), please report it to us as described below. ## Reporting Security Issues @@ -12,19 +12,19 @@ If you believe you have found a security vulnerability in any Microsoft-owned re Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). -If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). -You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: - * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) - * Full paths of source file(s) related to the manifestation of the issue - * The location of the affected source code (tag/branch/commit or direct URL) - * Any special configuration required to reproduce the issue - * Step-by-step instructions to reproduce the issue - * Proof-of-concept or exploit code (if possible) - * Impact of the issue, including how an attacker might exploit the issue +- Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) +- Full paths of source file(s) related to the manifestation of the issue +- The location of the affected source code (tag/branch/commit or direct URL) +- Any special configuration required to reproduce the issue +- Step-by-step instructions to reproduce the issue +- Proof-of-concept or exploit code (if possible) +- Impact of the issue, including how an attacker might exploit the issue This information will help us triage your report more quickly. @@ -38,4 +38,4 @@ We prefer all communications to be in English. Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). - \ No newline at end of file + diff --git a/samples/javascript/05.dice-roller-turbo/azure-pipelines.yml b/samples/javascript/05.dice-roller-turbo/azure-pipelines.yml index 411742198..094e7ea06 100644 --- a/samples/javascript/05.dice-roller-turbo/azure-pipelines.yml +++ b/samples/javascript/05.dice-roller-turbo/azure-pipelines.yml @@ -4,27 +4,27 @@ # FluidHelloWorld build for CI pr: -- main + - main -pool: 'Lite' +pool: "Lite" steps: -- task: ComponentGovernanceComponentDetection@0 - inputs: - scanType: 'Register' - verbosity: 'Verbose' - alertWarningLevel: 'High' -- task: UseNode@1 - displayName: Use Node 12.x - inputs: - version: 12.x -- task: Npm@1 - displayName: Install - inputs: - command: 'custom' - customCommand: 'install' -- task: Npm@1 - displayName: Build - inputs: - command: 'custom' - customCommand: 'run build' + - task: ComponentGovernanceComponentDetection@0 + inputs: + scanType: "Register" + verbosity: "Verbose" + alertWarningLevel: "High" + - task: UseNode@1 + displayName: Use Node 12.x + inputs: + version: 12.x + - task: Npm@1 + displayName: Install + inputs: + command: "custom" + customCommand: "install" + - task: Npm@1 + displayName: Build + inputs: + command: "custom" + customCommand: "run build" diff --git a/samples/javascript/05.dice-roller-turbo/package.json b/samples/javascript/05.dice-roller-turbo/package.json index 0b526405e..93c7d981b 100644 --- a/samples/javascript/05.dice-roller-turbo/package.json +++ b/samples/javascript/05.dice-roller-turbo/package.json @@ -13,22 +13,20 @@ "start:https": "vite src --config vite.https-config.js", "start:server": "npx tinylicious@latest", "start": "start-server-and-test start:server 7070 start:client", - "doctor": "eslint src/**/*.{j,t}s{,x} --fix --no-error-on-unmatched-pattern", - "postinstall":"node ../../../ensure-packages-built.js" + "doctor": "eslint src/**/*.{j,t}s{,x} --fix --no-error-on-unmatched-pattern" }, "dependencies": { - "@fluidframework/azure-client": "^1.1.1", - "@microsoft/live-share": "1.4.0", - "@microsoft/live-share-turbo": "1.4.0-preview.0", + "@fluidframework/azure-client": ">=2.40 <2.120", + "@microsoft/live-share": "2.0.0-internal.18", "@microsoft/teams-js": "^2.16.0", - "fluid-framework": "^1.3.6" + "fluid-framework": ">=2.40 <2.120" }, "devDependencies": { - "@fluidframework/test-client-utils": "^1.3.6", - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.7", + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", "buffer": "^6.0.3", "start-server-and-test": "^2.0.0", - "vite": "^4.0.4" + "vite": "^6.1.7" } } diff --git a/samples/javascript/05.dice-roller-turbo/src/app.js b/samples/javascript/05.dice-roller-turbo/src/app.js index b50b5f630..5d51762af 100644 --- a/samples/javascript/05.dice-roller-turbo/src/app.js +++ b/samples/javascript/05.dice-roller-turbo/src/app.js @@ -3,9 +3,13 @@ * Licensed under the MIT License. */ -import { TestLiveShareHost, LiveState } from "@microsoft/live-share"; -import { LiveShareTurboClient } from "@microsoft/live-share-turbo"; +import { + TestLiveShareHost, + LiveState, + LiveShareClient, +} from "@microsoft/live-share"; import { app, pages, meeting, LiveShareHost } from "@microsoft/teams-js"; +import { getInsecureTokenProvider } from "./insecureTokenProvider"; const searchParams = new URL(window.location).searchParams; const root = document.getElementById("content"); @@ -57,10 +61,10 @@ async function join() { // Are we running in teams? const host = searchParams.get("inTeams") ? LiveShareHost.create() - : TestLiveShareHost.create(); + : TestLiveShareHost.create(getInsecureTokenProvider()); // Create client & join session - const client = new LiveShareTurboClient(host); + const client = new LiveShareClient(host); await client.join(); return client; } diff --git a/samples/javascript/05.dice-roller-turbo/src/index.html b/samples/javascript/05.dice-roller-turbo/src/index.html index d71d95cce..1706b5d19 100644 --- a/samples/javascript/05.dice-roller-turbo/src/index.html +++ b/samples/javascript/05.dice-roller-turbo/src/index.html @@ -1,7 +1,7 @@ - + diff --git a/samples/javascript/05.dice-roller-turbo/src/insecureTokenProvider.js b/samples/javascript/05.dice-roller-turbo/src/insecureTokenProvider.js new file mode 100644 index 000000000..29806de5f --- /dev/null +++ b/samples/javascript/05.dice-roller-turbo/src/insecureTokenProvider.js @@ -0,0 +1,21 @@ +import { InsecureTokenProvider } from "@fluidframework/test-runtime-utils/internal"; +import { v4 as uuid } from "uuid"; + +export function getInsecureTokenProvider() { + const userId = () => { + try { + const userIdParam = new URL( + window.location.href + )?.searchParams?.get("userId"); + return userIdParam; + } catch { + // window not available + return undefined; + } + }; + const tokenProvider = new InsecureTokenProvider("", { + id: userId() ?? uuid(), + name: "Test User", + }); + return tokenProvider; +} diff --git a/samples/javascript/21.react-media-template/README.md b/samples/javascript/21.react-media-template/README.md index 36316ff8a..78a30a26d 100644 --- a/samples/javascript/21.react-media-template/README.md +++ b/samples/javascript/21.react-media-template/README.md @@ -13,12 +13,9 @@ After cloning the repository, you must first set up the npm workspace from the r ```bash npm install -npm run build:packages # Build Live Share packages cd samples/j*/21* ``` -_Note:_ Do not run `npm start` before running `npm run build:packages` from the root of the project, unless you first move the sample out of this npm workspace. When using our samples, you are testing the packages using symlinks, and not the Live Share SDK versions published to npm. - ## Testing locally in browser ### `npm run start` diff --git a/samples/javascript/21.react-media-template/index.html b/samples/javascript/21.react-media-template/index.html index 979f56e68..153d3f584 100644 --- a/samples/javascript/21.react-media-template/index.html +++ b/samples/javascript/21.react-media-template/index.html @@ -1,23 +1,20 @@ - + - - - - - - - - - React Media Template - - - -
        - - - + --> diff --git a/samples/javascript/21.react-media-template/package.json b/samples/javascript/21.react-media-template/package.json index e05bc5f73..6d4dba8e1 100644 --- a/samples/javascript/21.react-media-template/package.json +++ b/samples/javascript/21.react-media-template/package.json @@ -5,15 +5,15 @@ "author": "Microsoft", "license": "MIT", "dependencies": { + "@fluidframework/azure-client": ">=2.40 <2.120", "@fluentui/react-components": "^9.18.6", "@fluentui/react-icons": "^2.0.202", "@fluentui/react-theme": "^9.1.5", - "@fluidframework/azure-client": "^1.1.1", - "@microsoft/live-share": "1.4.0", - "@microsoft/live-share-canvas": "1.4.0", - "@microsoft/live-share-media": "1.4.0", + "@microsoft/live-share": "2.0.0-internal.18", + "@microsoft/live-share-canvas": "2.0.0-internal.18", + "@microsoft/live-share-media": "2.0.0-internal.18", "@microsoft/teams-js": "^2.16.0", - "fluid-framework": "^1.3.6", + "fluid-framework": ">=2.40 <2.120", "lodash": "^4.17.21", "prop-types": "^15.8.1", "react": "^18.2.0", @@ -25,20 +25,20 @@ "web-vitals": "^3.1.1" }, "devDependencies": { - "@fluidframework/test-client-utils": "^1.3.6", - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.7", - "@vitejs/plugin-react": "^3.0.1", + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "@vitejs/plugin-react": "^5.1.4", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.4.3", "dotenv-cli": "^7.2.1", - "eslint": "^8.41.0", - "eslint-config-prettier": "^8.8.0", - "eslint-plugin-prettier": "^4.2.1", - "prettier": "^2.8.8", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.1.3", + "prettier": "^3.3.3", "start-server-and-test": "^2.0.0", - "vite": "^4.0.4" + "vite": "^6.1.7" }, "scripts": { "build": "vite build", @@ -48,8 +48,7 @@ "start-https": "start-server-and-test start:server 7070 start:https", "start:client": "vite", "start:https": "vite --config vite.https-config.js", - "start:server": "npx tinylicious@latest", - "postinstall":"node ../../../ensure-packages-built.js" + "start:server": "npx tinylicious@latest" }, "browserslist": { "production": [ diff --git a/samples/javascript/21.react-media-template/public/manifest.json b/samples/javascript/21.react-media-template/public/manifest.json index 080d6c77a..f01493ff0 100644 --- a/samples/javascript/21.react-media-template/public/manifest.json +++ b/samples/javascript/21.react-media-template/public/manifest.json @@ -1,25 +1,25 @@ { - "short_name": "React App", - "name": "Create React App Sample", - "icons": [ - { - "src": "favicon.ico", - "sizes": "64x64 32x32 24x24 16x16", - "type": "image/x-icon" - }, - { - "src": "logo192.png", - "type": "image/png", - "sizes": "192x192" - }, - { - "src": "logo512.png", - "type": "image/png", - "sizes": "512x512" - } - ], - "start_url": ".", - "display": "standalone", - "theme_color": "#000000", - "background_color": "#ffffff" + "short_name": "React App", + "name": "Create React App Sample", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + }, + { + "src": "logo192.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "logo512.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" } diff --git a/samples/javascript/21.react-media-template/src/App.jsx b/samples/javascript/21.react-media-template/src/App.jsx index 1e9fba89f..8ea227b04 100644 --- a/samples/javascript/21.react-media-template/src/App.jsx +++ b/samples/javascript/21.react-media-template/src/App.jsx @@ -51,17 +51,17 @@ export default function App() { setTeamsTheme(teamsLightTheme); break; } - microsoftTeams.app.registerOnThemeChangeHandler(function ( - theme - ) { - if (theme == "dark") { - setTeamsTheme(teamsDarkTheme); - } else if (theme == "contrast") { - setTeamsTheme(teamsHighContrastTheme); - } else { - setTeamsTheme(teamsLightTheme); + microsoftTeams.app.registerOnThemeChangeHandler( + function (theme) { + if (theme == "dark") { + setTeamsTheme(teamsDarkTheme); + } else if (theme == "contrast") { + setTeamsTheme(teamsHighContrastTheme); + } else { + setTeamsTheme(teamsLightTheme); + } } - }); + ); } catch (error) { console.error(error); } diff --git a/samples/javascript/21.react-media-template/src/components/PlayerProgressBar.jsx b/samples/javascript/21.react-media-template/src/components/PlayerProgressBar.jsx index 29e612e38..486af887c 100644 --- a/samples/javascript/21.react-media-template/src/components/PlayerProgressBar.jsx +++ b/samples/javascript/21.react-media-template/src/components/PlayerProgressBar.jsx @@ -38,7 +38,10 @@ const PlayerProgressBar = ({ }, [onSeek, setIsSeeking, localCurrentTime]); // eslint-disable-next-line - const debouncedSeek = useCallback(debounce(onDidSeek, 200), [onDidSeek, localCurrentTime]); + const debouncedSeek = useCallback(debounce(onDidSeek, 200), [ + onDidSeek, + localCurrentTime, + ]); useEffect(() => { if (!isSeeking && currentTime !== localCurrentTime) { diff --git a/samples/javascript/21.react-media-template/src/index.css b/samples/javascript/21.react-media-template/src/index.css index 53ebb2200..d2536659f 100644 --- a/samples/javascript/21.react-media-template/src/index.css +++ b/samples/javascript/21.react-media-template/src/index.css @@ -1,17 +1,18 @@ body { - margin: 0; - min-height: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-size: calc(1em * 0.625); - display: "inline-block"; - overflow: "hidden"; + margin: 0; + min-height: 0; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", + "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-size: calc(1em * 0.625); + display: "inline-block"; + overflow: "hidden"; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; + font-family: + source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } diff --git a/samples/javascript/21.react-media-template/src/live-share-hooks/useMediaSession.js b/samples/javascript/21.react-media-template/src/live-share-hooks/useMediaSession.js index 5ae69c201..ea198883a 100644 --- a/samples/javascript/21.react-media-template/src/live-share-hooks/useMediaSession.js +++ b/samples/javascript/21.react-media-template/src/live-share-hooks/useMediaSession.js @@ -3,12 +3,12 @@ * Licensed under the MIT License. */ -// eslint-disable-next-line -import { UserMeetingRole } from "@microsoft/live-share"; -// eslint-disable-next-line +import { + LiveDataObjectInitializeState, + UserMeetingRole, +} from "@microsoft/live-share"; import { LiveMediaSession } from "@microsoft/live-share-media"; import { useState, useEffect, useCallback, useRef } from "react"; -// eslint-disable-next-line import { AzureMediaPlayer } from "../utils/AzureMediaPlayer"; import { inTeams } from "../utils/inTeams"; import * as microsoftTeams from "@microsoft/teams-js"; @@ -164,7 +164,8 @@ export const useMediaSession = ( useEffect(() => { if ( !mediaSession || - mediaSession.isInitialized || + mediaSession.initializeState == + LiveDataObjectInitializeState.succeeded || synchronizerRef.current || !selectedMediaItem || !player || diff --git a/samples/javascript/21.react-media-template/src/live-share-hooks/usePlaylist.js b/samples/javascript/21.react-media-template/src/live-share-hooks/usePlaylist.js index ff4d9744f..9be7c8f7c 100644 --- a/samples/javascript/21.react-media-template/src/live-share-hooks/usePlaylist.js +++ b/samples/javascript/21.react-media-template/src/live-share-hooks/usePlaylist.js @@ -78,7 +78,9 @@ export const usePlaylist = (playlistMap, sendNotification) => { }, [playlistMap, setMediaItems, setSelectedId]); // eslint-disable-next-line - const debouncedRefresh = useCallback(debounce(refreshMediaItems, 100), [refreshMediaItems]); + const debouncedRefresh = useCallback(debounce(refreshMediaItems, 100), [ + refreshMediaItems, + ]); useEffect(() => { if (playlistMap && !playlistStarted) { diff --git a/samples/javascript/21.react-media-template/src/live-share-hooks/usePresence.js b/samples/javascript/21.react-media-template/src/live-share-hooks/usePresence.js index de2179e86..c37663e2c 100644 --- a/samples/javascript/21.react-media-template/src/live-share-hooks/usePresence.js +++ b/samples/javascript/21.react-media-template/src/live-share-hooks/usePresence.js @@ -7,7 +7,7 @@ import { LivePresence, UserMeetingRole, ITimestampProvider, - PresenceState, + PresenceStatus, } from "@microsoft/live-share"; import { useState, useEffect, useRef, useMemo } from "react"; import { app } from "@microsoft/teams-js"; @@ -71,7 +71,7 @@ export const usePresence = ( setLocalUser(userPresence); } // Set users local state - const userArray = presence.getUsers(PresenceState.online); + const userArray = presence.getUsers(PresenceStatus.online); // Need to create new array so that React knows the user list changed. setUsers([...userArray]); }); diff --git a/samples/javascript/21.react-media-template/src/live-share-hooks/useSharedObjects.js b/samples/javascript/21.react-media-template/src/live-share-hooks/useSharedObjects.js index 5e18f2e7d..ab11a5440 100644 --- a/samples/javascript/21.react-media-template/src/live-share-hooks/useSharedObjects.js +++ b/samples/javascript/21.react-media-template/src/live-share-hooks/useSharedObjects.js @@ -4,14 +4,14 @@ */ import { LiveShareClient, TestLiveShareHost } from "@microsoft/live-share"; -import { InsecureTokenProvider } from "@fluidframework/test-client-utils"; import { LiveCanvas } from "@microsoft/live-share-canvas"; import { LiveMediaSession } from "@microsoft/live-share-media"; -import { SharedMap } from "fluid-framework"; +import { SharedMap } from "fluid-framework/legacy"; import { useEffect, useRef, useState } from "react"; import { LiveEvent, LivePresence } from "@microsoft/live-share"; import { mediaList } from "../utils/media-list"; import { LiveShareHost } from "@microsoft/teams-js"; +import { getInsecureTokenProvider } from "../utils/insecureTokenProvider"; /** * Hook that creates/loads the apps shared objects. @@ -77,13 +77,13 @@ export function useSharedObjects() { // Create live share host const host = inTeams ? LiveShareHost.create() - : TestLiveShareHost.create(); + : TestLiveShareHost.create(getInsecureTokenProvider()); // Create the client, join container, and set results console.log("useSharedObjects: joining container"); const client = new LiveShareClient(host); client - .joinContainer(schema, onFirstInitialize) + .join(schema, onFirstInitialize) .then((results) => { console.log("useSharedObjects: joined container"); setResults(results); diff --git a/samples/javascript/21.react-media-template/src/live-share-hooks/useTakeControl.js b/samples/javascript/21.react-media-template/src/live-share-hooks/useTakeControl.js index 9594168f2..8309ed0ac 100644 --- a/samples/javascript/21.react-media-template/src/live-share-hooks/useTakeControl.js +++ b/samples/javascript/21.react-media-template/src/live-share-hooks/useTakeControl.js @@ -1,7 +1,6 @@ import { useCallback, useEffect, useMemo, useState } from "react"; import { ITimestampProvider } from "@microsoft/live-share"; -// eslint-disable-next-line -import { SharedMap } from "fluid-framework"; +import { SharedMap } from "fluid-framework/legacy"; /** * @param {boolean} localUserIsEligiblePresenter boolean that is true when local user is eligible presenter @@ -32,7 +31,7 @@ export const useTakeControl = ( const mappedUsers = users.map((user) => { return { userId: user.userId, - state: user.state, + state: user.status, data: user.data, lastInControlTimestamp: user.userId ? history.get(user.userId) diff --git a/samples/javascript/21.react-media-template/src/utils/insecureTokenProvider.js b/samples/javascript/21.react-media-template/src/utils/insecureTokenProvider.js new file mode 100644 index 000000000..29806de5f --- /dev/null +++ b/samples/javascript/21.react-media-template/src/utils/insecureTokenProvider.js @@ -0,0 +1,21 @@ +import { InsecureTokenProvider } from "@fluidframework/test-runtime-utils/internal"; +import { v4 as uuid } from "uuid"; + +export function getInsecureTokenProvider() { + const userId = () => { + try { + const userIdParam = new URL( + window.location.href + )?.searchParams?.get("userId"); + return userIdParam; + } catch { + // window not available + return undefined; + } + }; + const tokenProvider = new InsecureTokenProvider("", { + id: userId() ?? uuid(), + name: "Test User", + }); + return tokenProvider; +} diff --git a/samples/javascript/22.react-agile-poker/README.md b/samples/javascript/22.react-agile-poker/README.md index 62888b701..1fb599fb1 100644 --- a/samples/javascript/22.react-agile-poker/README.md +++ b/samples/javascript/22.react-agile-poker/README.md @@ -12,12 +12,9 @@ After cloning the repository, you must first set up the npm workspace from the r ```bash npm install -npm run build:packages # Build Live Share packages cd samples/j*/22* ``` -_Note:_ Do not run `npm start` before running `npm run build:packages` from the root of the project, unless you first move the sample out of this npm workspace. When using our samples, you are testing the packages using symlinks, and not the Live Share SDK versions published to npm. - ## Testing locally in browser ### `npm run start` diff --git a/samples/javascript/22.react-agile-poker/index.html b/samples/javascript/22.react-agile-poker/index.html index f99c523e9..404e174a9 100644 --- a/samples/javascript/22.react-agile-poker/index.html +++ b/samples/javascript/22.react-agile-poker/index.html @@ -1,23 +1,20 @@ - + - - - - - - - - - React App - - - -
        - - - + --> diff --git a/samples/javascript/22.react-agile-poker/package.json b/samples/javascript/22.react-agile-poker/package.json index deca0c003..8e5acb8a0 100644 --- a/samples/javascript/22.react-agile-poker/package.json +++ b/samples/javascript/22.react-agile-poker/package.json @@ -5,13 +5,13 @@ "author": "Microsoft", "license": "MIT", "dependencies": { + "@fluidframework/azure-client": ">=2.40 <2.120", "@fluentui/react-components": "^9.18.6", "@fluentui/react-icons": "^2.0.202", "@fluentui/react-theme": "^9.1.5", - "@fluidframework/azure-client": "^1.1.1", - "@microsoft/live-share": "1.4.0", + "@microsoft/live-share": "2.0.0-internal.18", "@microsoft/teams-js": "^2.16.0", - "fluid-framework": "^1.3.6", + "fluid-framework": ">=2.40 <2.120", "prop-types": "^15.8.1", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -21,19 +21,19 @@ "web-vitals": "^3.1.1" }, "devDependencies": { - "@fluidframework/test-client-utils": "^1.3.6", + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.4.3", - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.7", - "@vitejs/plugin-react": "^3.0.1", - "eslint": "^8.41.0", - "eslint-config-prettier": "^8.8.0", - "eslint-plugin-prettier": "^4.2.1", - "prettier": "^2.8.8", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "@vitejs/plugin-react": "^5.1.4", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.1.3", + "prettier": "^3.3.3", "start-server-and-test": "^2.0.0", - "vite": "^4.0.4" + "vite": "^6.1.7" }, "scripts": { "clean": "npx shx rm -rf dist", @@ -44,8 +44,7 @@ "start:https": "vite --config vite.https-config.js", "build": "vite build", "preview": "vite preview", - "doctor": "eslint src/**/*.{j,t}s{,x} --fix --no-error-on-unmatched-pattern", - "postinstall":"node ../../../ensure-packages-built.js" + "doctor": "eslint src/**/*.{j,t}s{,x} --fix --no-error-on-unmatched-pattern" }, "browserslist": { "production": [ diff --git a/samples/javascript/22.react-agile-poker/public/manifest.json b/samples/javascript/22.react-agile-poker/public/manifest.json index 080d6c77a..f01493ff0 100644 --- a/samples/javascript/22.react-agile-poker/public/manifest.json +++ b/samples/javascript/22.react-agile-poker/public/manifest.json @@ -1,25 +1,25 @@ { - "short_name": "React App", - "name": "Create React App Sample", - "icons": [ - { - "src": "favicon.ico", - "sizes": "64x64 32x32 24x24 16x16", - "type": "image/x-icon" - }, - { - "src": "logo192.png", - "type": "image/png", - "sizes": "192x192" - }, - { - "src": "logo512.png", - "type": "image/png", - "sizes": "512x512" - } - ], - "start_url": ".", - "display": "standalone", - "theme_color": "#000000", - "background_color": "#ffffff" + "short_name": "React App", + "name": "Create React App Sample", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + }, + { + "src": "logo192.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "logo512.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" } diff --git a/samples/javascript/22.react-agile-poker/src/App.css b/samples/javascript/22.react-agile-poker/src/App.css index 17c19713c..cea479d15 100644 --- a/samples/javascript/22.react-agile-poker/src/App.css +++ b/samples/javascript/22.react-agile-poker/src/App.css @@ -1,6 +1,6 @@ .App { - height: 100vh; - color: white; - display: flex; - flex-direction: column; -} \ No newline at end of file + height: 100vh; + color: white; + display: flex; + flex-direction: column; +} diff --git a/samples/javascript/22.react-agile-poker/src/App.jsx b/samples/javascript/22.react-agile-poker/src/App.jsx index 3acb70945..b3b174763 100644 --- a/samples/javascript/22.react-agile-poker/src/App.jsx +++ b/samples/javascript/22.react-agile-poker/src/App.jsx @@ -47,15 +47,15 @@ export default function App() { setWebTheme(webLightTheme); break; } - microsoftTeams.app.registerOnThemeChangeHandler(function ( - theme - ) { - if (theme == "dark") { - setWebTheme(webDarkTheme); - } else { - setWebTheme(webLightTheme); + microsoftTeams.app.registerOnThemeChangeHandler( + function (theme) { + if (theme == "dark") { + setWebTheme(webDarkTheme); + } else { + setWebTheme(webLightTheme); + } } - }); + ); } catch (error) { console.error(error); } diff --git a/samples/javascript/22.react-agile-poker/src/index.css b/samples/javascript/22.react-agile-poker/src/index.css index 0e19063da..eab2eece7 100644 --- a/samples/javascript/22.react-agile-poker/src/index.css +++ b/samples/javascript/22.react-agile-poker/src/index.css @@ -1,11 +1,12 @@ body { - margin: 0; - min-height: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-size: calc(1em * 0.625); - display: "inline-block"; + margin: 0; + min-height: 0; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", + "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-size: calc(1em * 0.625); + display: "inline-block"; } diff --git a/samples/javascript/22.react-agile-poker/src/live-share-hooks/usePresence.js b/samples/javascript/22.react-agile-poker/src/live-share-hooks/usePresence.js index 79bc4d0f1..8204e985d 100644 --- a/samples/javascript/22.react-agile-poker/src/live-share-hooks/usePresence.js +++ b/samples/javascript/22.react-agile-poker/src/live-share-hooks/usePresence.js @@ -4,7 +4,7 @@ */ import { useState, useEffect, useCallback, useRef } from "react"; -import { PresenceState } from "@microsoft/live-share"; +import { PresenceStatus } from "@microsoft/live-share"; import { getRandomAvatar } from "../utils/random-avatar"; import { useStateRef } from "../utils/useStateRef"; @@ -60,7 +60,7 @@ export const usePresence = (presence, context) => { if (local) { const localUser = { userId: userPresence.userId, - state: userPresence.state, + state: userPresence.status, data: userPresence.data, name: userPresence.displayName, roles: userPresence.roles, @@ -69,10 +69,10 @@ export const usePresence = (presence, context) => { } // Update our local state const updatedUsers = presence - .getUsers(PresenceState.online) + .getUsers(PresenceStatus.online) .map((userPresence) => ({ userId: userPresence.userId, - state: userPresence.state, + state: userPresence.status, data: userPresence.data, name: userPresence.displayName, roles: userPresence.roles, @@ -86,7 +86,7 @@ export const usePresence = (presence, context) => { avatarIndex: defaultAvatarInformation.avatarIndex, ready: false, }, - PresenceState.online + PresenceStatus.online ) .then(() => { setPresenceStarted(true); diff --git a/samples/javascript/22.react-agile-poker/src/live-share-hooks/useSharedObjects.js b/samples/javascript/22.react-agile-poker/src/live-share-hooks/useSharedObjects.js index 673f69c7a..fba0e6ca8 100644 --- a/samples/javascript/22.react-agile-poker/src/live-share-hooks/useSharedObjects.js +++ b/samples/javascript/22.react-agile-poker/src/live-share-hooks/useSharedObjects.js @@ -11,9 +11,10 @@ import { TestLiveShareHost, } from "@microsoft/live-share"; import { LiveTimer } from "@microsoft/live-share"; -import { SharedMap } from "fluid-framework"; +import { SharedMap } from "fluid-framework/legacy"; import { getDefaultUserStories } from "../constants/default-user-stories"; import { LiveShareHost } from "@microsoft/teams-js"; +import { getInsecureTokenProvider } from "../utils/insecureTokenProvider"; /** * Hook that creates/loads the apps shared objects. @@ -77,12 +78,12 @@ export function useSharedObjects() { // Create live share host const host = inTeams ? LiveShareHost.create() - : TestLiveShareHost.create(); + : TestLiveShareHost.create(getInsecureTokenProvider()); // Join Teams container const client = new LiveShareClient(host); client - .joinContainer(schema, onFirstInitialize) + .join(schema, onFirstInitialize) .then((results) => setResults(results)) .catch((err) => setError(err)); }, []); diff --git a/samples/javascript/22.react-agile-poker/src/utils/insecureTokenProvider.js b/samples/javascript/22.react-agile-poker/src/utils/insecureTokenProvider.js new file mode 100644 index 000000000..29806de5f --- /dev/null +++ b/samples/javascript/22.react-agile-poker/src/utils/insecureTokenProvider.js @@ -0,0 +1,21 @@ +import { InsecureTokenProvider } from "@fluidframework/test-runtime-utils/internal"; +import { v4 as uuid } from "uuid"; + +export function getInsecureTokenProvider() { + const userId = () => { + try { + const userIdParam = new URL( + window.location.href + )?.searchParams?.get("userId"); + return userIdParam; + } catch { + // window not available + return undefined; + } + }; + const tokenProvider = new InsecureTokenProvider("", { + id: userId() ?? uuid(), + name: "Test User", + }); + return tokenProvider; +} diff --git a/samples/javascript/23.react-live-canvas/README.md b/samples/javascript/23.react-live-canvas/README.md index 25ed6cb47..254d9873b 100644 --- a/samples/javascript/23.react-live-canvas/README.md +++ b/samples/javascript/23.react-live-canvas/README.md @@ -17,12 +17,9 @@ After cloning the repository, you must first set up the npm workspace from the r ```bash npm install -npm run build:packages # Build Live Share packages cd samples/j*/22* ``` -_Note:_ Do not run `npm start` before running `npm run build:packages` from the root of the project, unless you first move the sample out of this npm workspace. When using our samples, you are testing the packages using symlinks, and not the Live Share SDK versions published to npm. - ## Testing locally in browser ### `npm run start` diff --git a/samples/javascript/23.react-live-canvas/index.html b/samples/javascript/23.react-live-canvas/index.html index 696d38066..406577593 100644 --- a/samples/javascript/23.react-live-canvas/index.html +++ b/samples/javascript/23.react-live-canvas/index.html @@ -1,20 +1,20 @@ - + - - - - - - - - - React App - - - -
        - - - + --> diff --git a/samples/javascript/23.react-live-canvas/package.json b/samples/javascript/23.react-live-canvas/package.json index ee25c59b2..4ea2750a4 100644 --- a/samples/javascript/23.react-live-canvas/package.json +++ b/samples/javascript/23.react-live-canvas/package.json @@ -5,11 +5,11 @@ "author": "Microsoft", "license": "MIT", "dependencies": { - "@microsoft/live-share": "1.4.0", - "@microsoft/live-share-canvas": "1.4.0", + "@fluidframework/azure-client": ">=2.40 <2.120", + "@microsoft/live-share": "2.0.0-internal.18", + "@microsoft/live-share-canvas": "2.0.0-internal.18", "@microsoft/teams-js": "^2.16.0", - "@fluidframework/azure-client": "^1.1.1", - "fluid-framework": "^1.3.6", + "fluid-framework": ">=2.40 <2.120", "react": "^18.2.0", "react-dom": "^18.2.0", "react-router": "^6.4.2", @@ -18,19 +18,19 @@ "web-vitals": "^3.1.1" }, "devDependencies": { - "@fluidframework/test-client-utils": "^1.3.6", + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.4.3", - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.7", - "@vitejs/plugin-react": "^3.0.1", - "eslint": "^8.41.0", - "eslint-config-prettier": "^8.8.0", - "eslint-plugin-prettier": "^4.2.1", - "prettier": "^2.8.8", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "@vitejs/plugin-react": "^5.1.4", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.1.3", + "prettier": "^3.3.3", "start-server-and-test": "^2.0.0", - "vite": "^4.0.4" + "vite": "^6.1.7" }, "scripts": { "build": "vite build", @@ -41,8 +41,7 @@ "start:https": "vite --config vite.https-config.js", "doctor": "eslint src/**/*.{j,t}s{,x} --fix --no-error-on-unmatched-pattern", "start:server": "npx tinylicious@latest", - "start": "start-server-and-test start:server 7070 start:client", - "postinstall":"node ../../../ensure-packages-built.js" + "start": "start-server-and-test start:server 7070 start:client" }, "browserslist": { "production": [ diff --git a/samples/javascript/23.react-live-canvas/public/manifest.json b/samples/javascript/23.react-live-canvas/public/manifest.json index 080d6c77a..f01493ff0 100644 --- a/samples/javascript/23.react-live-canvas/public/manifest.json +++ b/samples/javascript/23.react-live-canvas/public/manifest.json @@ -1,25 +1,25 @@ { - "short_name": "React App", - "name": "Create React App Sample", - "icons": [ - { - "src": "favicon.ico", - "sizes": "64x64 32x32 24x24 16x16", - "type": "image/x-icon" - }, - { - "src": "logo192.png", - "type": "image/png", - "sizes": "192x192" - }, - { - "src": "logo512.png", - "type": "image/png", - "sizes": "512x512" - } - ], - "start_url": ".", - "display": "standalone", - "theme_color": "#000000", - "background_color": "#ffffff" + "short_name": "React App", + "name": "Create React App Sample", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + }, + { + "src": "logo192.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "logo512.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" } diff --git a/samples/javascript/23.react-live-canvas/src/App.css b/samples/javascript/23.react-live-canvas/src/App.css index 1e6f0e2fe..72564c951 100644 --- a/samples/javascript/23.react-live-canvas/src/App.css +++ b/samples/javascript/23.react-live-canvas/src/App.css @@ -1,13 +1,10 @@ - - #inkingRoot { - flex: 1 1 200%; + flex: 1 1 200%; } #inkingHost { - margin: 2%; - border-style: solid; - border-radius: 5px; - height: 100%; + margin: 2%; + border-style: solid; + border-radius: 5px; + height: 100%; } - diff --git a/samples/javascript/23.react-live-canvas/src/Pages/LiveCanvasPage.jsx b/samples/javascript/23.react-live-canvas/src/Pages/LiveCanvasPage.jsx index 2f1699987..bb6a628b9 100644 --- a/samples/javascript/23.react-live-canvas/src/Pages/LiveCanvasPage.jsx +++ b/samples/javascript/23.react-live-canvas/src/Pages/LiveCanvasPage.jsx @@ -1,8 +1,8 @@ import { LiveShareClient, TestLiveShareHost } from "@microsoft/live-share"; import { LiveCanvas, InkingTool } from "@microsoft/live-share-canvas"; -import { InsecureTokenProvider } from "@fluidframework/test-client-utils"; import { useEffect, useState, useRef, useCallback } from "react"; import { useLiveCanvas } from "../utils/useLiveCanvas"; +import { getInsecureTokenProvider } from "../utils/insecureTokenProvider"; const containerSchema = { initialObjects: { @@ -64,8 +64,10 @@ export const LiveCanvasPage = () => { }, [inkingManager]); const initialize = async () => { - const client = new LiveShareClient(TestLiveShareHost.create()); - const { container } = await client.joinContainer(containerSchema); + const client = new LiveShareClient( + TestLiveShareHost.create(getInsecureTokenProvider()) + ); + const { container } = await client.join(containerSchema); setliveCanvas(container.initialObjects.liveCanvas); }; diff --git a/samples/javascript/23.react-live-canvas/src/index.css b/samples/javascript/23.react-live-canvas/src/index.css index ec2585e8c..a2fefc9cc 100644 --- a/samples/javascript/23.react-live-canvas/src/index.css +++ b/samples/javascript/23.react-live-canvas/src/index.css @@ -1,13 +1,14 @@ body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + margin: 0; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", + "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; + font-family: + source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } diff --git a/samples/javascript/23.react-live-canvas/src/utils/insecureTokenProvider.js b/samples/javascript/23.react-live-canvas/src/utils/insecureTokenProvider.js new file mode 100644 index 000000000..29806de5f --- /dev/null +++ b/samples/javascript/23.react-live-canvas/src/utils/insecureTokenProvider.js @@ -0,0 +1,21 @@ +import { InsecureTokenProvider } from "@fluidframework/test-runtime-utils/internal"; +import { v4 as uuid } from "uuid"; + +export function getInsecureTokenProvider() { + const userId = () => { + try { + const userIdParam = new URL( + window.location.href + )?.searchParams?.get("userId"); + return userIdParam; + } catch { + // window not available + return undefined; + } + }; + const tokenProvider = new InsecureTokenProvider("", { + id: userId() ?? uuid(), + name: "Test User", + }); + return tokenProvider; +} diff --git a/samples/typescript/01.dice-roller/README.md b/samples/typescript/01.dice-roller/README.md index 924dd7e41..2327502b5 100644 --- a/samples/typescript/01.dice-roller/README.md +++ b/samples/typescript/01.dice-roller/README.md @@ -13,15 +13,11 @@ After cloning the repository, you must first set up the npm workspace from the r ```bash npm install -npm run build:packages # Build Live Share packages cd samples/t*/01* -npm start ``` Running `npm start`, it will do two things: start the `tinylicious` server and start the application using `vite`. If you have never used `tinylicious` before, you should see instead is a prompt saying `Ok to proceed? (y)`, after which you should type `y` and press the "enter" key. In rare cases you might not see the `Ok to proceed? (y)` prompt, in which case try running `npx tinylicious@latest` in your command line directly, and then try again. -_Note:_ Do not run `npm start` before running `npm run build:packages` from the root of the project, unless you first move the sample out of this npm workspace. When using our samples, you are testing the packages using symlinks, and not the Live Share SDK versions published to npm. - ## Testing the app in Teams ### Create a ngrok tunnel to allow Teams to reach your tab app diff --git a/samples/typescript/01.dice-roller/SECURITY.md b/samples/typescript/01.dice-roller/SECURITY.md index f7b89984f..105419313 100644 --- a/samples/typescript/01.dice-roller/SECURITY.md +++ b/samples/typescript/01.dice-roller/SECURITY.md @@ -4,7 +4,7 @@ Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). -If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below. +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](), please report it to us as described below. ## Reporting Security Issues @@ -12,19 +12,19 @@ If you believe you have found a security vulnerability in any Microsoft-owned re Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). -If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). -You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: - * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) - * Full paths of source file(s) related to the manifestation of the issue - * The location of the affected source code (tag/branch/commit or direct URL) - * Any special configuration required to reproduce the issue - * Step-by-step instructions to reproduce the issue - * Proof-of-concept or exploit code (if possible) - * Impact of the issue, including how an attacker might exploit the issue +- Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) +- Full paths of source file(s) related to the manifestation of the issue +- The location of the affected source code (tag/branch/commit or direct URL) +- Any special configuration required to reproduce the issue +- Step-by-step instructions to reproduce the issue +- Proof-of-concept or exploit code (if possible) +- Impact of the issue, including how an attacker might exploit the issue This information will help us triage your report more quickly. @@ -38,4 +38,4 @@ We prefer all communications to be in English. Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). - \ No newline at end of file + diff --git a/samples/typescript/01.dice-roller/azure-pipelines.yml b/samples/typescript/01.dice-roller/azure-pipelines.yml index 411742198..094e7ea06 100644 --- a/samples/typescript/01.dice-roller/azure-pipelines.yml +++ b/samples/typescript/01.dice-roller/azure-pipelines.yml @@ -4,27 +4,27 @@ # FluidHelloWorld build for CI pr: -- main + - main -pool: 'Lite' +pool: "Lite" steps: -- task: ComponentGovernanceComponentDetection@0 - inputs: - scanType: 'Register' - verbosity: 'Verbose' - alertWarningLevel: 'High' -- task: UseNode@1 - displayName: Use Node 12.x - inputs: - version: 12.x -- task: Npm@1 - displayName: Install - inputs: - command: 'custom' - customCommand: 'install' -- task: Npm@1 - displayName: Build - inputs: - command: 'custom' - customCommand: 'run build' + - task: ComponentGovernanceComponentDetection@0 + inputs: + scanType: "Register" + verbosity: "Verbose" + alertWarningLevel: "High" + - task: UseNode@1 + displayName: Use Node 12.x + inputs: + version: 12.x + - task: Npm@1 + displayName: Install + inputs: + command: "custom" + customCommand: "install" + - task: Npm@1 + displayName: Build + inputs: + command: "custom" + customCommand: "run build" diff --git a/samples/typescript/01.dice-roller/package.json b/samples/typescript/01.dice-roller/package.json index a916340bb..27b56c977 100644 --- a/samples/typescript/01.dice-roller/package.json +++ b/samples/typescript/01.dice-roller/package.json @@ -14,21 +14,20 @@ "start:server": "npx tinylicious@latest", "start-https": "start-server-and-test start:server 7070 start:https", "start": "start-server-and-test start:server 7070 start:client", - "doctor": "eslint src/**/*.{j,t}s{,x} --fix --no-error-on-unmatched-pattern", - "postinstall":"node ../../../ensure-packages-built.js" + "doctor": "eslint src/**/*.{j,t}s{,x} --fix --no-error-on-unmatched-pattern" }, "dependencies": { - "@fluidframework/azure-client": "^1.1.1", - "@microsoft/live-share": "1.4.0", + "@fluidframework/azure-client": ">=2.40 <2.120", + "@microsoft/live-share": "2.0.0-internal.18", "@microsoft/teams-js": "^2.16.0", - "fluid-framework": "^1.3.6" + "fluid-framework": ">=2.40 <2.120" }, "devDependencies": { - "@fluidframework/test-client-utils": "^1.3.6", - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.7", + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", "buffer": "^6.0.3", "start-server-and-test": "^2.0.0", - "vite": "^4.0.4" + "vite": "^6.1.7" } } diff --git a/samples/typescript/01.dice-roller/src/app.ts b/samples/typescript/01.dice-roller/src/app.ts index d7dbe505a..6b71bf8f1 100644 --- a/samples/typescript/01.dice-roller/src/app.ts +++ b/samples/typescript/01.dice-roller/src/app.ts @@ -3,36 +3,21 @@ * Licensed under the MIT License. */ -import { - LivePresence, - LiveShareClient, - LiveState, - TestLiveShareHost, -} from "@microsoft/live-share"; +import { LiveShareClient, TestLiveShareHost } from "@microsoft/live-share"; import { app, LiveShareHost } from "@microsoft/teams-js"; import { renderMeetingStage } from "./renderMeetingStage"; import { renderMeetingSidePanel } from "./renderMeetingSidePanel"; import { renderTabConfig } from "./renderTabConfig"; import { renderError } from "./renderError"; -import { SharedMap } from "fluid-framework"; -import { AppTheme, IPresenceData } from "./types-interfaces"; +import { AppTheme } from "./types-interfaces"; +import { getInsecureTokenProvider } from "./insecureTokenProvider"; const searchParams = new URL(window.location.href).searchParams; const IN_TEAMS = searchParams.get("inTeams") === "1"; const root = document.getElementById("content")!; let theme: AppTheme = "light"; -// Define container schema -const containerSchema = { - initialObjects: { - diceState: LiveState, // shared dice value, resets once all users close app - presence: LivePresence, // each user has their own dice value, resets once all users close app - storedDiceMap: SharedMap, // stored dice value that will last 6 hours from session creation - }, -}; - // STARTUP LOGIC - async function start() { // Check for page to display let view = searchParams.get("view") || "stage"; @@ -52,8 +37,8 @@ async function start() { // Load the requested view switch (view) { case "content": { - const { container } = await joinContainer(); - await renderMeetingSidePanel(container, root, theme); + const client = await getClient(); + await renderMeetingSidePanel(client, root, theme); break; } case "config": { @@ -62,22 +47,26 @@ async function start() { } case "stage": default: { - const { container } = await joinContainer(); - await renderMeetingStage(container, root, theme); + const client = await getClient(); + await renderMeetingStage(client, root, theme); break; } } } -async function joinContainer() { +async function getClient() { // Are we running in teams? - const host = IN_TEAMS ? LiveShareHost.create() : TestLiveShareHost.create(); + const host = IN_TEAMS + ? LiveShareHost.create() + : TestLiveShareHost.create(getInsecureTokenProvider()); // Create client const client = new LiveShareClient(host); // Join container - return await client.joinContainer(containerSchema); + await client.join(); + + return client; } start().catch((error) => renderError(root, error, theme)); diff --git a/samples/typescript/01.dice-roller/src/index.html b/samples/typescript/01.dice-roller/src/index.html index eee74bc2c..22c89bb50 100644 --- a/samples/typescript/01.dice-roller/src/index.html +++ b/samples/typescript/01.dice-roller/src/index.html @@ -1,7 +1,7 @@ - + @@ -13,8 +13,8 @@ Live Share - Dice Roller - +
        - \ No newline at end of file + diff --git a/samples/typescript/01.dice-roller/src/insecureTokenProvider.ts b/samples/typescript/01.dice-roller/src/insecureTokenProvider.ts new file mode 100644 index 000000000..37fef8212 --- /dev/null +++ b/samples/typescript/01.dice-roller/src/insecureTokenProvider.ts @@ -0,0 +1,22 @@ +import { ITokenProvider } from "@fluidframework/azure-client"; +import { InsecureTokenProvider } from "@fluidframework/test-runtime-utils/internal"; +import { v4 as uuid } from "uuid"; + +export function getInsecureTokenProvider(): ITokenProvider { + const userId: () => string | undefined | null = () => { + try { + const userIdParam = new URL( + window.location.href + )?.searchParams?.get("userId"); + return userIdParam; + } catch { + // window not available + return undefined; + } + }; + const tokenProvider = new InsecureTokenProvider("", { + id: userId() ?? uuid(), + name: "Test User", + }); + return tokenProvider as ITokenProvider; +} diff --git a/samples/typescript/01.dice-roller/src/renderMeetingSidePanel.ts b/samples/typescript/01.dice-roller/src/renderMeetingSidePanel.ts index 8a09169bb..5dfd0f7f9 100644 --- a/samples/typescript/01.dice-roller/src/renderMeetingSidePanel.ts +++ b/samples/typescript/01.dice-roller/src/renderMeetingSidePanel.ts @@ -5,15 +5,19 @@ import { meeting } from "@microsoft/teams-js"; import { getRandomDiceValue, stylizeDiceElem } from "./utils"; -import { IFluidContainer, SharedMap } from "fluid-framework"; +import { SharedMap } from "fluid-framework/legacy"; import { AppTheme } from "./types-interfaces"; +import { LiveShareClient } from "@microsoft/live-share"; export async function renderMeetingSidePanel( - container: IFluidContainer, + client: LiveShareClient, elem: HTMLElement, theme: AppTheme ) { - const storedDiceMap = container.initialObjects.storedDiceMap as SharedMap; + const storedDiceMap = await client.getDDS( + "storedDice", + SharedMap + ); const sideBarTemplate = document.createElement("template"); sideBarTemplate["innerHTML"] = `
        diff --git a/samples/typescript/01.dice-roller/src/renderMeetingStage.ts b/samples/typescript/01.dice-roller/src/renderMeetingStage.ts index 0d95ce92b..4b82d00a8 100644 --- a/samples/typescript/01.dice-roller/src/renderMeetingStage.ts +++ b/samples/typescript/01.dice-roller/src/renderMeetingStage.ts @@ -7,16 +7,16 @@ import { IClientInfo, LivePresence, LivePresenceUser, + LiveShareClient, LiveState, - PresenceState, + PresenceStatus, UserMeetingRole, } from "@microsoft/live-share"; import { getRandomDiceValue, stylizeDiceElem } from "./utils"; -import { IFluidContainer } from "fluid-framework"; import { AppTheme, IPresenceData } from "./types-interfaces"; export async function renderMeetingStage( - container: IFluidContainer, + client: LiveShareClient, elem: HTMLElement, theme: AppTheme ) { @@ -30,15 +30,19 @@ export async function renderMeetingStage(

        Users:

        `; - const { diceState, presence } = container.initialObjects; + const diceState = await client.getDDS>( + "dice", + LiveState + ); + const presence = await client.getDDS>( + "dice", + LivePresence + ); elem.appendChild(stageTemplate.content.cloneNode(true)); const wrapperElem = elem.querySelector(".wrapper")!; - await renderSharedDice(diceState as LiveState, wrapperElem); - await renderPresenceDiceList( - presence as LivePresence, - wrapperElem - ); + await renderSharedDice(diceState, wrapperElem); + await renderPresenceDiceList(presence, wrapperElem); } async function renderSharedDice( @@ -104,7 +108,7 @@ async function renderUserDice( const userDiceElementId = `user-dice-${userPresence.userId}`; let userDiceElement = document.getElementById(userDiceElementId); // If the user's state is not offline, remove it from the DOM - if (userPresence.state !== PresenceState.online) { + if (userPresence.status !== PresenceStatus.online) { userDiceElement?.remove(); return; } diff --git a/samples/typescript/01.dice-roller/src/styles.css b/samples/typescript/01.dice-roller/src/styles.css index 6657a2bbb..83fd04058 100644 --- a/samples/typescript/01.dice-roller/src/styles.css +++ b/samples/typescript/01.dice-roller/src/styles.css @@ -2,7 +2,7 @@ text-align: center; max-height: 100vh; overflow-y: none; - font-family: "Segoe UI" + font-family: "Segoe UI"; } .wrapper.light { color: black; diff --git a/samples/typescript/01.dice-roller/tsconfig.json b/samples/typescript/01.dice-roller/tsconfig.json index 06541f3b8..8b811ccb8 100644 --- a/samples/typescript/01.dice-roller/tsconfig.json +++ b/samples/typescript/01.dice-roller/tsconfig.json @@ -1,74 +1,75 @@ { "compilerOptions": { - /* Visit https://aka.ms/tsconfig.json to read more about this file */ - - /* Basic Options */ - // "incremental": true, /* Enable incremental compilation */ - "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ - "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ - "lib": ["es2020","DOM"], /* Specify library files to be included in the compilation. */ - "allowJs": false, /* Allow javascript files to be compiled. */ - // "checkJs": true, /* Report errors in .js files. */ - // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ - "declaration": true, /* Generates corresponding '.d.ts' file. */ - "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ - "sourceMap": true, /* Generates corresponding '.map' file. */ - // "outFile": "./", /* Concatenate and emit output to single file. */ - "outDir": "./bin", /* Redirect output structure to the directory. */ - // "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ - // "composite": true, /* Enable project compilation */ - // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ - // "removeComments": true, /* Do not emit comments to output. */ - // "noEmit": true, /* Do not emit outputs. */ - // "importHelpers": true, /* Import emit helpers from 'tslib'. */ - // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ - // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ - - /* Strict Type-Checking Options */ - "strict": true, /* Enable all strict type-checking options. */ - // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* Enable strict null checks. */ - // "strictFunctionTypes": true, /* Enable strict checking of function types. */ - // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ - // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ - // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ - // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ - - /* Additional Checks */ - // "noUnusedLocals": true, /* Report errors on unused locals. */ - // "noUnusedParameters": true, /* Report errors on unused parameters. */ - // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ - // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - - /* Module Resolution Options */ - // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ - // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ - // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ - // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ - // "typeRoots": [], /* List of folders to include type definitions from. */ - // "types": [], /* Type declaration files to be included in compilation. */ - // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ - "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ - // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - - /* Source Map Options */ - // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ - // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ - - /* Experimental Options */ - // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ - // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ - - /* Advanced Options */ - "skipLibCheck": true, /* Skip type checking of declaration files. */ - "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Basic Options */ + // "incremental": true, /* Enable incremental compilation */ + "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */, + "module": "ESNext" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, + "moduleResolution": "bundler", + "lib": [ + "es2020", + "DOM" + ] /* Specify library files to be included in the compilation. */, + "allowJs": false /* Allow javascript files to be compiled. */, + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + "declaration": true /* Generates corresponding '.d.ts' file. */, + "declarationMap": true /* Generates a sourcemap for each corresponding '.d.ts' file. */, + "sourceMap": true /* Generates corresponding '.map' file. */, + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "./bin" /* Redirect output structure to the directory. */, + // "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + + /* Strict Type-Checking Options */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + + /* Module Resolution Options */ + // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + + /* Advanced Options */ + "skipLibCheck": true /* Skip type checking of declaration files. */, + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ }, "exclude": ["build", "dist", "node_modules"], - "files": [ - "src/app.ts" - ] - } - \ No newline at end of file + "files": ["src/app.ts"] +} diff --git a/samples/typescript/03.live-canvas-demo/README.md b/samples/typescript/03.live-canvas-demo/README.md index 5ffc39409..5eda28b5a 100644 --- a/samples/typescript/03.live-canvas-demo/README.md +++ b/samples/typescript/03.live-canvas-demo/README.md @@ -8,12 +8,9 @@ After cloning the repository, you must first set up the npm workspace from the r ```bash npm install -npm run build:packages # Build Live Share packages cd samples/t*/03* ``` -_Note:_ Do not run `npm start` before running `npm run build:packages` from the root of the project, unless you first move the sample out of this npm workspace. When using our samples, you are testing the packages using symlinks, and not the Live Share SDK versions published to npm. - ## Testing locally in browser ### `npm run start` diff --git a/samples/typescript/03.live-canvas-demo/package.json b/samples/typescript/03.live-canvas-demo/package.json index 3042f3172..a8748438f 100644 --- a/samples/typescript/03.live-canvas-demo/package.json +++ b/samples/typescript/03.live-canvas-demo/package.json @@ -13,22 +13,21 @@ "start:client": "vite", "start:https": "vite --config vite.https-config.js", "start:server": "npx tinylicious@latest", - "doctor": "eslint src/**/*.{j,t}s{,x} --fix --no-error-on-unmatched-pattern", - "postinstall":"node ../../../ensure-packages-built.js" + "doctor": "eslint src/**/*.{j,t}s{,x} --fix --no-error-on-unmatched-pattern" }, "dependencies": { - "@fluidframework/azure-client": "^1.1.1", - "@microsoft/live-share": "1.4.0", - "@microsoft/live-share-canvas": "1.4.0", + "@fluidframework/azure-client": ">=2.40 <2.120", + "@microsoft/live-share": "2.0.0-internal.18", + "@microsoft/live-share-canvas": "2.0.0-internal.18", "@microsoft/teams-js": "^2.16.0", - "fluid-framework": "^1.3.6" + "fluid-framework": ">=2.40 <2.120" }, "devDependencies": { - "@fluidframework/test-client-utils": "^1.3.6", - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.7", + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", "buffer": "^6.0.3", "start-server-and-test": "^2.0.0", - "vite": "^4.0.4" + "vite": "^6.1.7" } } diff --git a/samples/typescript/03.live-canvas-demo/src/app.css b/samples/typescript/03.live-canvas-demo/src/app.css index 80a929bcb..2b0ec2626 100644 --- a/samples/typescript/03.live-canvas-demo/src/app.css +++ b/samples/typescript/03.live-canvas-demo/src/app.css @@ -1,6 +1,6 @@ * { box-sizing: border-box; - font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; } body { @@ -19,7 +19,16 @@ body { flex: 1 1 100%; position: relative; overflow: hidden; - background-image: linear-gradient(#444cf7 0.6000000000000001px, transparent 0.6000000000000001px), linear-gradient(to right, #444cf7 0.6000000000000001px, transparent 0.6000000000000001px); + background-image: + linear-gradient( + #444cf7 0.6000000000000001px, + transparent 0.6000000000000001px + ), + linear-gradient( + to right, + #444cf7 0.6000000000000001px, + transparent 0.6000000000000001px + ); background-size: 12px 12px; } @@ -51,21 +60,21 @@ body { font-weight: 600; padding: 2px 10px 3px 10px; -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - background-color: #EEEEEE; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-color: #eeeeee; color: black; border: 1px solid #888888; border-radius: 2px; } .toolbar > button:hover { - background-color: #DDDDDD; + background-color: #dddddd; border: 1px solid #777777; } .toolbar > button:active { - background-color: #CCCCCC; + background-color: #cccccc; border: 1px solid #777777; -} \ No newline at end of file +} diff --git a/samples/typescript/03.live-canvas-demo/src/index.html b/samples/typescript/03.live-canvas-demo/src/index.html index b36f8f1c9..5ac6bd3cd 100644 --- a/samples/typescript/03.live-canvas-demo/src/index.html +++ b/samples/typescript/03.live-canvas-demo/src/index.html @@ -1,4 +1,4 @@ - + diff --git a/samples/typescript/03.live-canvas-demo/src/insecureTokenProvider.ts b/samples/typescript/03.live-canvas-demo/src/insecureTokenProvider.ts new file mode 100644 index 000000000..37fef8212 --- /dev/null +++ b/samples/typescript/03.live-canvas-demo/src/insecureTokenProvider.ts @@ -0,0 +1,22 @@ +import { ITokenProvider } from "@fluidframework/azure-client"; +import { InsecureTokenProvider } from "@fluidframework/test-runtime-utils/internal"; +import { v4 as uuid } from "uuid"; + +export function getInsecureTokenProvider(): ITokenProvider { + const userId: () => string | undefined | null = () => { + try { + const userIdParam = new URL( + window.location.href + )?.searchParams?.get("userId"); + return userIdParam; + } catch { + // window not available + return undefined; + } + }; + const tokenProvider = new InsecureTokenProvider("", { + id: userId() ?? uuid(), + name: "Test User", + }); + return tokenProvider as ITokenProvider; +} diff --git a/samples/typescript/03.live-canvas-demo/src/stage-view.ts b/samples/typescript/03.live-canvas-demo/src/stage-view.ts index cf0ca904a..60170ffda 100644 --- a/samples/typescript/03.live-canvas-demo/src/stage-view.ts +++ b/samples/typescript/03.live-canvas-demo/src/stage-view.ts @@ -10,9 +10,9 @@ import { InkingTool, LiveCanvas, } from "@microsoft/live-share-canvas"; -import { IFluidContainer } from "fluid-framework"; import * as Utils from "./utils"; import { View } from "./view"; +import { getInsecureTokenProvider } from "./insecureTokenProvider"; /** * Other images @@ -60,15 +60,9 @@ const appTemplate = ` `; -const containerSchema = { - initialObjects: { - liveCanvas: LiveCanvas, - }, -}; - export class StageView extends View { private _inkingManager!: InkingManager; - private _container!: IFluidContainer; + private _client!: LiveShareClient; private offsetBy(x: number, y: number) { this._inkingManager.offset = { @@ -79,8 +73,8 @@ export class StageView extends View { this.updateBackgroundImagePosition(); } - private getLiveCanvas(): LiveCanvas { - return this._container.initialObjects.liveCanvas as LiveCanvas; + private async getLiveCanvas(): Promise { + return await this._client.getDDS("liveCanvas", LiveCanvas); } private _hostResizeObserver!: ResizeObserver; @@ -88,17 +82,15 @@ export class StageView extends View { private async internalStart() { const host = Utils.runningInTeams() ? Teams.LiveShareHost.create() - : TestLiveShareHost.create(); + : TestLiveShareHost.create(getInsecureTokenProvider()); const client = new LiveShareClient(host); - - this._container = ( - await client.joinContainer(containerSchema) - ).container; + await client.join(); + this._client = client; const inkingHost = document.getElementById("inkingHost"); if (inkingHost) { - const liveCanvas = this.getLiveCanvas(); + const liveCanvas = await this.getLiveCanvas(); this._inkingManager = new InkingManager(inkingHost); @@ -265,8 +257,8 @@ export class StageView extends View { this.updateBackgroundImagePosition(); }); - setupButton("btnToggleCursorShare", () => { - const liveCanvas = this.getLiveCanvas(); + setupButton("btnToggleCursorShare", async () => { + const liveCanvas = await this.getLiveCanvas(); const isCursorShared = liveCanvas.isCursorShared; liveCanvas.isCursorShared = !isCursorShared; diff --git a/samples/typescript/03.live-canvas-demo/tsconfig.json b/samples/typescript/03.live-canvas-demo/tsconfig.json index 06541f3b8..8b811ccb8 100644 --- a/samples/typescript/03.live-canvas-demo/tsconfig.json +++ b/samples/typescript/03.live-canvas-demo/tsconfig.json @@ -1,74 +1,75 @@ { "compilerOptions": { - /* Visit https://aka.ms/tsconfig.json to read more about this file */ - - /* Basic Options */ - // "incremental": true, /* Enable incremental compilation */ - "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ - "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ - "lib": ["es2020","DOM"], /* Specify library files to be included in the compilation. */ - "allowJs": false, /* Allow javascript files to be compiled. */ - // "checkJs": true, /* Report errors in .js files. */ - // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ - "declaration": true, /* Generates corresponding '.d.ts' file. */ - "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ - "sourceMap": true, /* Generates corresponding '.map' file. */ - // "outFile": "./", /* Concatenate and emit output to single file. */ - "outDir": "./bin", /* Redirect output structure to the directory. */ - // "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ - // "composite": true, /* Enable project compilation */ - // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ - // "removeComments": true, /* Do not emit comments to output. */ - // "noEmit": true, /* Do not emit outputs. */ - // "importHelpers": true, /* Import emit helpers from 'tslib'. */ - // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ - // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ - - /* Strict Type-Checking Options */ - "strict": true, /* Enable all strict type-checking options. */ - // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* Enable strict null checks. */ - // "strictFunctionTypes": true, /* Enable strict checking of function types. */ - // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ - // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ - // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ - // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ - - /* Additional Checks */ - // "noUnusedLocals": true, /* Report errors on unused locals. */ - // "noUnusedParameters": true, /* Report errors on unused parameters. */ - // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ - // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - - /* Module Resolution Options */ - // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ - // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ - // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ - // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ - // "typeRoots": [], /* List of folders to include type definitions from. */ - // "types": [], /* Type declaration files to be included in compilation. */ - // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ - "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ - // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - - /* Source Map Options */ - // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ - // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ - - /* Experimental Options */ - // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ - // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ - - /* Advanced Options */ - "skipLibCheck": true, /* Skip type checking of declaration files. */ - "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Basic Options */ + // "incremental": true, /* Enable incremental compilation */ + "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */, + "module": "ESNext" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, + "moduleResolution": "bundler", + "lib": [ + "es2020", + "DOM" + ] /* Specify library files to be included in the compilation. */, + "allowJs": false /* Allow javascript files to be compiled. */, + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + "declaration": true /* Generates corresponding '.d.ts' file. */, + "declarationMap": true /* Generates a sourcemap for each corresponding '.d.ts' file. */, + "sourceMap": true /* Generates corresponding '.map' file. */, + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "./bin" /* Redirect output structure to the directory. */, + // "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + + /* Strict Type-Checking Options */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + + /* Module Resolution Options */ + // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + + /* Advanced Options */ + "skipLibCheck": true /* Skip type checking of declaration files. */, + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ }, "exclude": ["build", "dist", "node_modules"], - "files": [ - "src/app.ts" - ] - } - \ No newline at end of file + "files": ["src/app.ts"] +} diff --git a/samples/typescript/04.live-share-react/README.md b/samples/typescript/04.live-share-react/README.md index 962d8ef1a..844a2727c 100644 --- a/samples/typescript/04.live-share-react/README.md +++ b/samples/typescript/04.live-share-react/README.md @@ -10,12 +10,9 @@ After cloning the repository, you must first set up the npm workspace from the r ```bash npm install -npm run build:packages # Build Live Share packages cd samples/t*/04* ``` -_Note:_ Do not run `npm start` before running `npm run build:packages` from the root of the project, unless you first move the sample out of this npm workspace. When using our samples, you are testing the packages using symlinks, and not the Live Share SDK versions published to npm. - ## Testing locally in browser ### `npm run start` diff --git a/samples/typescript/04.live-share-react/index.html b/samples/typescript/04.live-share-react/index.html index b66500383..9b1d54b1c 100644 --- a/samples/typescript/04.live-share-react/index.html +++ b/samples/typescript/04.live-share-react/index.html @@ -1,23 +1,20 @@ - + - - - - - - - - - Live Share React Demo - - - -
        - - - + --> diff --git a/samples/typescript/04.live-share-react/package.json b/samples/typescript/04.live-share-react/package.json index da00c7fb3..3c99812ab 100644 --- a/samples/typescript/04.live-share-react/package.json +++ b/samples/typescript/04.live-share-react/package.json @@ -5,16 +5,16 @@ "author": "Microsoft", "license": "MIT", "dependencies": { + "@fluidframework/azure-client": ">=2.40 <2.120", "@fluentui/react-components": "^9.18.6", "@fluentui/react-icons": "^2.0.202", "@fluentui/react-theme": "^9.1.5", - "@fluidframework/azure-client": "^1.1.1", - "@microsoft/live-share": "1.4.0", - "@microsoft/live-share-media": "1.4.0", - "@microsoft/live-share-canvas": "1.4.0", - "@microsoft/live-share-react": "1.4.0-preview.0", + "@microsoft/live-share": "2.0.0-internal.18", + "@microsoft/live-share-media": "2.0.0-internal.18", + "@microsoft/live-share-canvas": "2.0.0-internal.18", + "@microsoft/live-share-react": "2.0.0-internal.18", "@microsoft/teams-js": "^2.16.0", - "fluid-framework": "^1.3.6", + "fluid-framework": ">=2.40 <2.120", "lodash": "^4.17.21", "prop-types": "^15.8.1", "react": "^18.2.0", @@ -26,20 +26,20 @@ "web-vitals": "^3.1.1" }, "devDependencies": { - "@fluidframework/test-client-utils": "^1.3.6", + "@fluidframework/test-runtime-utils": ">=2.40 <2.120", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.4.3", - "@typescript-eslint/eslint-plugin": "^5.59.2", - "@typescript-eslint/parser": "^5.59.7", - "@vitejs/plugin-react": "^3.0.1", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "@vitejs/plugin-react": "^5.1.4", "dotenv-cli": "^7.2.1", - "eslint": "^8.41.0", - "eslint-config-prettier": "^8.8.0", - "eslint-plugin-prettier": "^4.2.1", - "prettier": "^2.8.8", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.1.3", + "prettier": "^3.3.3", "start-server-and-test": "^2.0.0", - "vite": "^4.0.4" + "vite": "^6.1.7" }, "scripts": { "build": "vite build", @@ -49,8 +49,7 @@ "start-https": "start-server-and-test start:server 7070 start:https", "start:client": "vite", "start:https": "vite --config vite.https-config.ts", - "start:server": "npx tinylicious@latest", - "postinstall":"node ../../../ensure-packages-built.js" + "start:server": "npx tinylicious@latest" }, "browserslist": { "production": [ diff --git a/samples/typescript/04.live-share-react/public/manifest.json b/samples/typescript/04.live-share-react/public/manifest.json index 080d6c77a..f01493ff0 100644 --- a/samples/typescript/04.live-share-react/public/manifest.json +++ b/samples/typescript/04.live-share-react/public/manifest.json @@ -1,25 +1,25 @@ { - "short_name": "React App", - "name": "Create React App Sample", - "icons": [ - { - "src": "favicon.ico", - "sizes": "64x64 32x32 24x24 16x16", - "type": "image/x-icon" - }, - { - "src": "logo192.png", - "type": "image/png", - "sizes": "192x192" - }, - { - "src": "logo512.png", - "type": "image/png", - "sizes": "512x512" - } - ], - "start_url": ".", - "display": "standalone", - "theme_color": "#000000", - "background_color": "#ffffff" + "short_name": "React App", + "name": "Create React App Sample", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + }, + { + "src": "logo192.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "logo512.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" } diff --git a/samples/typescript/04.live-share-react/src/App.tsx b/samples/typescript/04.live-share-react/src/App.tsx index 19ce0a170..9959d054c 100644 --- a/samples/typescript/04.live-share-react/src/App.tsx +++ b/samples/typescript/04.live-share-react/src/App.tsx @@ -9,6 +9,7 @@ import { TabConfig, } from "./pages"; import { AppRoutes } from "./constants"; +import { FluentProvider, teamsLightTheme } from "@fluentui/react-components"; const IN_TEAMS = inTeams(); @@ -42,7 +43,7 @@ export default function App() { const appReady = (IN_TEAMS && initialized) || !IN_TEAMS; return ( - <> + {appReady && ( @@ -74,6 +75,6 @@ export default function App() { )} - + ); } diff --git a/samples/typescript/04.live-share-react/src/components/ExampleLiveCanvas.tsx b/samples/typescript/04.live-share-react/src/components/ExampleLiveCanvas.tsx index f728c1d65..3a7bdc46e 100644 --- a/samples/typescript/04.live-share-react/src/components/ExampleLiveCanvas.tsx +++ b/samples/typescript/04.live-share-react/src/components/ExampleLiveCanvas.tsx @@ -2,6 +2,7 @@ import { useLiveCanvas } from "@microsoft/live-share-react"; import { InkingTool } from "@microsoft/live-share-canvas"; import { FC, useState } from "react"; import { useRef } from "react"; +import { FlexRow } from "./internals/flex"; export const ExampleLiveCanvas: FC = () => { const liveCanvasRef = useRef(null); @@ -11,67 +12,99 @@ export const ExampleLiveCanvas: FC = () => { const { inkingManager, liveCanvas } = useLiveCanvas( "CUSTOM-LIVE-CANVAS", liveCanvasRef, - active, - tool, - undefined, - undefined, - undefined, - undefined, - isCursorShared + { + active, + tool, + isCursorShared, + } ); return (
        -
        - {!!liveCanvas && ( -
        - - - - - - -
        - )} + +
        + +
        + {!!liveCanvas && ( + + + + + + + + + + + + )} +
        ); }; diff --git a/samples/typescript/04.live-share-react/src/components/ExampleLiveEvent.tsx b/samples/typescript/04.live-share-react/src/components/ExampleLiveEvent.tsx index 45dd4f22f..1e04d54b4 100644 --- a/samples/typescript/04.live-share-react/src/components/ExampleLiveEvent.tsx +++ b/samples/typescript/04.live-share-react/src/components/ExampleLiveEvent.tsx @@ -1,19 +1,43 @@ import { useLiveEvent } from "@microsoft/live-share-react"; -import { FC } from "react"; +import { FC, useState } from "react"; export const ExampleLiveEvent: FC = () => { const { latestEvent, allEvents, sendEvent } = useLiveEvent("EVENT-ID"); + const [targetClientId, setTargetClientId] = useState(""); return (
        {/* Render counts of notifications sent/received */} -
        {`Total received: ${ - allEvents.filter((event) => !event.local).length - }`}
        -
        {`Total sent: ${ - allEvents.filter((event) => event.local).length - }`}
        +
        + Total received: + {` ${allEvents.filter((event) => !event.local).length}`} +
        +
        + Total sent: + {` ${allEvents.filter((event) => event.local).length}`} +
        + {/* Show latest reaction */} + {latestEvent?.local === false && ( +
        + Received: + {` ${latestEvent?.value}, `} + From: + {` ${latestEvent?.clientId}`} +
        + )} + {latestEvent?.local === true && ( +
        + Sent: + {` ${latestEvent?.value}`} +
        + )} + {!latestEvent && ( +
        + Latest: + {` N/A`} +
        + )} {/* Buttons for sending reactions */}
        - {/* Show latest reaction */} - {latestEvent?.local === false && ( -
        {`Received: ${latestEvent?.value}`}
        - )} - {latestEvent?.local === true && ( -
        {`Sent: ${latestEvent?.value}`}
        - )} + { + setTargetClientId(ev.target.value); + }} + /> +
        ); diff --git a/samples/typescript/04.live-share-react/src/components/ExampleLivePresence.tsx b/samples/typescript/04.live-share-react/src/components/ExampleLivePresence.tsx index 6fcf6a3b7..b2b41ca52 100644 --- a/samples/typescript/04.live-share-react/src/components/ExampleLivePresence.tsx +++ b/samples/typescript/04.live-share-react/src/components/ExampleLivePresence.tsx @@ -1,17 +1,12 @@ -import { PresenceState } from "@microsoft/live-share"; import { useLivePresence } from "@microsoft/live-share-react"; import { FC } from "react"; export const ExampleLivePresence: FC = () => { - const { - localUser, - allUsers, - updatePresence, - livePresence: v1, - } = useLivePresence( - "CUSTOM-PRESENCE-KEY", - { toggleCount: 0 } // optional - ); + const { localUser, allUsers, updatePresence, livePresence } = + useLivePresence("CUSTOM-PRESENCE-KEY", { count: 0 }); + + if (!livePresence) return <>Loading presence...; + return (

        {"Users:"}

        @@ -20,29 +15,19 @@ export const ExampleLivePresence: FC = () => {
        {`${user.displayName}, isLocalUser: ${user.isLocalUser}, toggleCount: ${user.data?.toggleCount}`}
        + >{`${user.displayName}, isLocalUser: ${user.isLocalUser}, count: ${user.data?.count}`}
        ))}
        ); diff --git a/samples/typescript/04.live-share-react/src/components/ExampleLiveState.tsx b/samples/typescript/04.live-share-react/src/components/ExampleLiveState.tsx index 24931afca..53bd7d4c7 100644 --- a/samples/typescript/04.live-share-react/src/components/ExampleLiveState.tsx +++ b/samples/typescript/04.live-share-react/src/components/ExampleLiveState.tsx @@ -3,30 +3,51 @@ import { useLiveShareContext, useLiveState, } from "@microsoft/live-share-react"; -import { UserMeetingRole, LiveShareClient } from "@microsoft/live-share"; -import { FC, ReactNode, useState } from "react"; +import { UserMeetingRole } from "@microsoft/live-share"; +import { FC, ReactNode, useMemo, useState } from "react"; +import { ExampleSharedTree } from "./ExampleSharedTree"; +import { FlexColumn } from "./internals/flex"; +import { NavigationBar } from "./internals/NavigationBar"; +import { + Dropdown, + Option, + useId, + DropdownProps, + Title1, + Caption1, +} from "@fluentui/react-components"; +import { ExampleLiveCanvas } from "./ExampleLiveCanvas"; +import { ExampleLiveEvent } from "./ExampleLiveEvent"; +import { ExampleLivePresence } from "./ExampleLivePresence"; +import { ExampleLiveTimer } from "./ExampleLiveTimer"; +import { ExampleMediaSynchronizer } from "./ExampleMediaSynchronizer"; +import { ExampleSharedMap } from "./ExampleSharedMap"; +import { ExampleSharedState } from "./ExampleSharedState"; -enum ExampleAppStatus { - WAITING = "WAITING", - START = "START", +enum OpenDDS { + useLiveCanvas = "useLiveCanvas", + useLiveEvent = "useLiveEvent", + useMediaSynchronizer = "useMediaSynchronizer", + useSharedState = "useSharedState", + useSharedTree = "useSharedTree", + useLiveTimer = "useLiveTimer", + useLivePresence = "useLivePresence", + useSharedMap = "useSharedMap", } +const options = Object.keys(OpenDDS); interface ILiveStateData { - status: ExampleAppStatus; + status: OpenDDS | null; timeStarted?: number; } const ALLOWED_ROLES = [UserMeetingRole.organizer, UserMeetingRole.presenter]; const INITIAL_STATE: ILiveStateData = { - status: ExampleAppStatus.WAITING, + status: null, }; -interface IExampleStateProps { - waitingContent: ReactNode; - startContent: ReactNode; -} - -export const ExampleLiveState: FC = (props) => { +export const ExampleLiveState: FC = () => { + const dropdownId = useId("dropdown-default"); const [state, setState] = useLiveState( "CUSTOM-STATE-ID", INITIAL_STATE, @@ -34,45 +55,65 @@ export const ExampleLiveState: FC = (props) => { ); const { timestampProvider } = useLiveShareContext(); - if (state.status === ExampleAppStatus.WAITING) { - return ( -
        -
        -

        {`Start round:`}

        - - -
        -

        {"Welcome to Fluid React!"}

        - {props.waitingContent} -
        - ); - } + const onOptionSelect: DropdownProps["onOptionSelect"] = (ev, data) => { + if (!data.optionText || !(data.optionText in OpenDDS)) return; + setState({ + timeStarted: timestampProvider?.getTimestamp(), + status: data.optionText as OpenDDS, + }); + }; + return ( -
        -
        -

        {`Time started: ${state.timeStarted}`}

        - - -
        - {props.startContent} -
        + + + + + {options.map((option) => ( + + ))} + + + + + {state.status === null && ( + + {"Welcome to Live Share React!"} + + {"Pick a hook to test from the dropdown above"} + + + )} + {state.status === OpenDDS.useLiveCanvas && ( + + )} + {state.status === OpenDDS.useLiveEvent && } + {state.status === OpenDDS.useLivePresence && ( + + )} + {state.status === OpenDDS.useLiveTimer && } + {state.status === OpenDDS.useMediaSynchronizer && ( + + )} + {state.status === OpenDDS.useSharedMap && } + {state.status === OpenDDS.useSharedState && ( + + )} + {state.status === OpenDDS.useSharedTree && ( + + )} + + ); }; diff --git a/samples/typescript/04.live-share-react/src/components/ExampleSharedMap.tsx b/samples/typescript/04.live-share-react/src/components/ExampleSharedMap.tsx index 3f2cf6c3b..4f5dc5902 100644 --- a/samples/typescript/04.live-share-react/src/components/ExampleSharedMap.tsx +++ b/samples/typescript/04.live-share-react/src/components/ExampleSharedMap.tsx @@ -7,10 +7,14 @@ import { FC } from "react"; export const EXAMPLE_SHARED_MAP_KEY = "CUSTOM-CARDS-MAP"; export const ExampleSharedMap: FC = () => { - const { map, setEntry, deleteEntry } = useSharedMap( + const { sharedMap, deleteEntry, setEntry } = useSharedMap( EXAMPLE_SHARED_MAP_KEY ); + if (!sharedMap) { + return <>Loading...; + } + return (
        @@ -28,7 +32,7 @@ export const ExampleSharedMap: FC = () => {
        - {[...map.values()].map((cardValue) => ( + {[...sharedMap.values()].map((cardValue) => ( NoteComment, +]) { + public addNode(author: string) { + const timeStamp = new Date().getTime(); + + // Define the note to add to the SharedTree - this must conform to + // the schema definition of a note + const newVote = new NoteComment({ + id: uuid(), + text: "", + author, + votes: [], + created: timeStamp, + lastChanged: timeStamp, + }); + + // Insert the note into the SharedTree. + this.insertAtEnd(newVote); + } +} + +export class NoteHeader extends sf.object("NoteHeader", { + color: sf.optional(sf.string), + emoji: sf.optional(sf.string), +}) { + setRandomVibrantColor() { + const vibrantColors: string[] = [ + "#FF5733", // Vibrant Red-Orange + "#FFBD33", // Vibrant Orange + "#FFD733", // Vibrant Yellow + "#33FF57", // Vibrant Green + "#33FFBD", // Vibrant Aqua + "#33D7FF", // Vibrant Sky Blue + "#3357FF", // Vibrant Blue + "#8D33FF", // Vibrant Purple + "#FF33BD", // Vibrant Pink + "#FF3357", // Vibrant Red + ]; + + const randomIndex: number = Math.floor( + Math.random() * vibrantColors.length + ); + this.color = vibrantColors[randomIndex]; + } + setRandomEmoji() { + const vibrantEmojis: string[] = [ + "🌟", // Star + "🔥", // Fire + "🌈", // Rainbow + "🍓", // Strawberry + "🍊", // Tangerine + "🍋", // Lemon + "🍀", // Four Leaf Clover + "🌸", // Cherry Blossom + "🎨", // Palette + "🎉", // Party Popper + ]; + + const randomIndex: number = Math.floor( + Math.random() * vibrantEmojis.length + ); + this.emoji = vibrantEmojis[randomIndex]; + } +} + +// Define the schema for the note object. +// Helper functions for working with the data contained in this object +// are included in this class definition as methods. +export class Note extends sf.object( + "Note", + // Fields for Notes which SharedTree will store and synchronize across clients. + // These fields are exposed as members of instances of the Note class. + { + /** + * Id to make building the React app simpler. + */ + id: sf.string, + text: sf.string, + author: sf.string, + /** + * Sequence of user ids to track which users have voted on this note. + */ + votes: sf.array(sf.string), + created: sf.number, + lastChanged: sf.number, + header: NoteHeader, + comments: NoteComments, + } +) { + // Update the note text and also update the timestamp in the note + public updateText(text: string) { + this.lastChanged = new Date().getTime(); + this.text = text; + } + + public toggleVote(user: string) { + const index = this.votes.indexOf(user); + if (index > -1) { + this.votes.removeAt(index); + } else { + this.votes.insertAtEnd(user); + } + } + + /** + * Removes a node from its parent {@link Notes}. + * If the note is not in an {@link Notes}, it is left unchanged. + */ + public delete() { + const parent = Tree.parent(this); + // Use type narrowing to ensure that parent is Items as expected for a note. + if (Tree.is(parent, Notes)) { + const index = parent.indexOf(this); + parent.removeAt(index); + } + } +} + +export type INote = typeof Note; + +// Schema for a list of Notes and Groups. +export class Notes extends sf.array("Notes", [() => Note]) { + public addNode(author: string) { + const timeStamp = new Date().getTime(); + + // Define the note to add to the SharedTree - this must conform to + // the schema definition of a note + const newNote = new Note({ + id: uuid(), + text: "", + author, + votes: [], + created: timeStamp, + lastChanged: timeStamp, + comments: [], + header: new NoteHeader({ + emoji: undefined, + color: undefined, + }), + }); + + // Insert the note into the SharedTree. + this.insertAtEnd(newNote); + } +} + +// Export the tree config appropriate for this schema. +// This is passed into the SharedTree when it is initialized. +export const appTreeConfiguration = new TreeViewConfiguration( + // Schema for the root + { schema: Notes } +); diff --git a/samples/typescript/04.live-share-react/src/components/ExampleSharedTree.tsx b/samples/typescript/04.live-share-react/src/components/ExampleSharedTree.tsx new file mode 100644 index 000000000..705ef1f04 --- /dev/null +++ b/samples/typescript/04.live-share-react/src/components/ExampleSharedTree.tsx @@ -0,0 +1,143 @@ +import { useSharedTree, useTreeNode } from "@microsoft/live-share-react"; +import { FC, memo, useCallback, ChangeEvent } from "react"; +import { + Note, + NoteHeader, + Notes, + appTreeConfiguration, +} from "./ExampleSharedTree-schema"; +import { Textarea, TextareaOnChangeData } from "@fluentui/react-components"; + +const initialData = new Notes([]); + +export const EXAMPLE_SHARED_TREE_KEY = "MY-TREE"; + +export const ExampleSharedTree: FC = () => { + // Live Share hook that creates a new SharedTree instance dynamically. + // `root` is of type `Notes`, which is just a list of `Note` nodes. + const { root } = useSharedTree( + EXAMPLE_SHARED_TREE_KEY, + appTreeConfiguration, + initialData + ); + + // Live Share hook that makes the `root` value stateful. + // By default, all child nodes of `notes` are not stateful and must be passed into `useTreeNode`. + const { node: notes } = useTreeNode(root); + + if (!root) { + return <>Loading root...; + } + if (!notes) { + return <>Loading notes...; + } + return ( +
        +
        +

        {"Notes"}

        + +
        +
        + {notes.map((note) => ( + + ))} +
        +
        + ); +}; + +interface INoteStickyProps { + noteNode: Note; +} + +const NoteSticky: FC = ({ noteNode }) => { + // Makes the `noteNode` value stateful to React. + // Here we use the "treeChanged" prop, which will ensure all child nodes are stateful also. + // Since this note is a pretty small component, it is pretty safe to do this here. + const { node: note } = useTreeNode(noteNode, "treeChanged"); + const onTextChange = useCallback( + (_: ChangeEvent, data: TextareaOnChangeData) => { + note.text = data.value; + }, + [note] + ); + return ( +
        + +
        {`${note.author} | ${note.votes.length} votes`}
        +
        +