diff --git a/.github/workflows/typescript-bindings.yml b/.github/workflows/typescript-bindings.yml
new file mode 100644
index 000000000..f2a6ad3cd
--- /dev/null
+++ b/.github/workflows/typescript-bindings.yml
@@ -0,0 +1,184 @@
+name: TypeScript bindings
+
+on:
+ push:
+ branches: [master]
+ paths:
+ - "typescript/**"
+ - ".github/workflows/typescript-bindings.yml"
+ pull_request:
+ branches: [master]
+ paths:
+ - "typescript/**"
+ - ".github/workflows/typescript-bindings.yml"
+ workflow_dispatch:
+
+env:
+ CARGO_TERM_COLOR: always
+
+# The JS/Wasm bindings live under `typescript/`, which is a self-contained Cargo
+# workspace (it pulls `rapier2d`/`rapier3d` from crates.io, not from the crates
+# in this repo). Every step therefore runs inside that directory.
+
+concurrency:
+ group: typescript-bindings-${{ github.ref }}
+ cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
+
+jobs:
+ check-fmt:
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: typescript
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-node@v4
+ with:
+ node-version: "22.x"
+ - run: npm ci
+ - name: Check formatting
+ run: npm run fmt -- --check
+ - name: Check Rust formatting
+ run: cargo fmt -- --check
+ build:
+ strategy:
+ matrix:
+ os: [ubuntu-latest, macos-latest]
+ runs-on: ${{ matrix.os }}
+ defaults:
+ run:
+ working-directory: typescript
+ env:
+ RUSTFLAGS: -D warnings
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/cache@v4
+ with:
+ path: |
+ ~/.cargo/bin/
+ ~/.cargo/registry/index/
+ ~/.cargo/registry/cache/
+ ~/.cargo/git/db/
+ typescript/target/
+ key: ${{ runner.os }}-cargo-js-${{ hashFiles('typescript/builds/prepare_builds/templates/Cargo.toml.tera') }}
+ restore-keys: |
+ ${{ runner.os }}-cargo-js-
+ - run: npm ci;
+ - name: Prepare no-compat builds
+ run: |
+ ./builds/prepare_builds/prepare_all_projects.sh
+ - name: Build all no-compat projects
+ run: |
+ ./builds/prepare_builds/build_all_projects.sh
+ # Install dependencies to check simd for builds
+ - name: Install wabt
+ run: |
+ sudo apt install wabt;
+ if: matrix.os == 'ubuntu-latest'
+ - name: Install wabt
+ run: |
+ brew install wabt;
+ if: matrix.os == 'macos-latest'
+ # Check simd for rust builds
+ - name: Check 2d simd rust build
+ run: |
+ if ! wasm-objdump -d builds/rapier2d-simd/pkg/rapier_wasm2d_bg.wasm | grep :\\sfd ; then
+ >&2 echo "ERROR: 2d simd compat build does not include simd opcode prefix." && exit 1
+ fi
+ - name: Check 3d simd compat build
+ run: |
+ if ! wasm-objdump -d builds/rapier3d-simd/pkg/rapier_wasm3d_bg.wasm | grep :\\sfd ; then
+ >&2 echo "ERROR: 3d simd compat build does not include simd opcode prefix." && exit 1
+ fi
+ - uses: actions/upload-artifact@v4
+ with:
+ name: pkg no-compat ${{ matrix.os }}
+ path: |
+ typescript/builds/*/pkg
+ overwrite: true
+ build-compat:
+ strategy:
+ matrix:
+ os: [ubuntu-latest, macos-latest]
+ runs-on: ${{ matrix.os }}
+ defaults:
+ run:
+ working-directory: typescript
+ env:
+ RUSTFLAGS: -D warnings
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/cache@v4
+ with:
+ path: |
+ ~/.cargo/bin/
+ ~/.cargo/registry/index/
+ ~/.cargo/registry/cache/
+ ~/.cargo/git/db/
+ typescript/target/
+ key: ${{ runner.os }}-cargo-js-${{ hashFiles('typescript/builds/prepare_builds/templates/Cargo.toml.tera') }}
+ restore-keys: |
+ ${{ runner.os }}-cargo-js-
+ - run: npm ci;
+ - name: Prepare compat builds
+ run: |
+ ./builds/prepare_builds/prepare_all_projects.sh
+ - name: Build rapier-compat
+ run: |
+ cd rapier-compat;
+ npm ci;
+ npm run build;
+ npm run test;
+ # Install dependencies to check simd for builds
+ - name: Install wabt
+ run: |
+ sudo apt install wabt;
+ if: matrix.os == 'ubuntu-latest'
+ - name: Install wabt
+ run: |
+ brew install wabt;
+ if: matrix.os == 'macos-latest'
+ # Check simd for compat builds
+ - name: Check 2d simd compat build
+ run: |
+ if ! wasm-objdump -d rapier-compat/builds/2d-simd/pkg/rapier_wasm2d_bg.wasm | grep :\\sfd ; then
+ >&2 echo "ERROR: 2d simd compat build does not include simd opcode prefix." && exit 1;
+ fi
+ - name: Check 3d simd compat build
+ run: |
+ if ! wasm-objdump -d rapier-compat/builds/3d-simd/pkg/rapier_wasm3d_bg.wasm | grep :\\sfd ; then
+ >&2 echo "ERROR: 3d simd compat build does not include simd opcode prefix." && exit 1;
+ fi
+ # Upload
+ - uses: actions/upload-artifact@v4
+ with:
+ name: pkg compat ${{ matrix.os }}
+ path: |
+ typescript/rapier-compat/builds/*/pkg
+ overwrite: true
+ publish:
+ runs-on: ubuntu-latest
+ needs: [build, build-compat]
+ if: github.ref == 'refs/heads/master'
+ defaults:
+ run:
+ working-directory: typescript
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/download-artifact@v4
+ with:
+ name: pkg no-compat ubuntu-latest
+ path: typescript/builds
+ - uses: actions/download-artifact@v4
+ with:
+ name: pkg compat ubuntu-latest
+ path: typescript/rapier-compat/builds
+ - uses: actions/setup-node@v4
+ with:
+ node-version: "22.x"
+ registry-url: "https://registry.npmjs.org"
+ - name: Publish projects
+ run: |
+ ./publish_all_canary.sh
+ env:
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
diff --git a/.typos.toml b/.typos.toml
index ca5c20cf4..b0123245a 100644
--- a/.typos.toml
+++ b/.typos.toml
@@ -30,6 +30,8 @@ Shepperd = "Shepperd"
# with `bb`) and `typ` (a "type" value — `type` is reserved in Rust/Python).
ba = "ba"
typ = "typ"
+# Voxel grid coordinate index in the JS bindings, paired with `ix`/`iz`.
+iy = "iy"
# Template mesh data in the testbed instancer: `tpos`/`tnrm`/`tidx`
# (template positions/normals/indices). Only `tpos` collides with a word.
tpos = "tpos"
diff --git a/Cargo.toml b/Cargo.toml
index ac588c7d9..e881c8049 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -39,6 +39,9 @@ default-members = [
"crates/mjcf-rs",
"crates/rapier3d-mjcf",
]
+# `typescript/` is the JS/Wasm bindings' own Cargo workspace; keep it out of
+# this one so root-level `cargo` commands never try to absorb its crates.
+exclude = ["typescript"]
resolver = "2"
[workspace.package]
diff --git a/typescript/.gitignore b/typescript/.gitignore
new file mode 100644
index 000000000..3b3fe48a7
--- /dev/null
+++ b/typescript/.gitignore
@@ -0,0 +1,27 @@
+# Ignore rules specific to the TypeScript/Wasm bindings. Generic entries
+# (node_modules, target, .idea, .DS_Store) already live in the repository-root
+# .gitignore and are not repeated here.
+
+# The root .gitignore excludes `package-lock.json`, but the JS bindings must
+# commit it: `npm ci` (used throughout the JS CI) requires the lockfile. The
+# Rust `Cargo.lock` stays ignored (matching the repo root): the workspace's only
+# members are the `prepare_builds`-generated crates, so a committed lock would
+# just churn with generated entries; CI regenerates it.
+!package-lock.json
+
+**/*.rs.bk
+dist
+pkg
+gen2d/
+gen3d/
+docs
+*.swp
+*.d.ts
+
+# Per-target crates generated by the `prepare_builds` crate; only the
+# generator itself is tracked.
+builds/*
+!builds/prepare_builds
+
+# Compat package's generated wasm builds.
+rapier-compat/builds/
diff --git a/typescript/.prettierignore b/typescript/.prettierignore
new file mode 100644
index 000000000..24ed3cdd9
--- /dev/null
+++ b/typescript/.prettierignore
@@ -0,0 +1,7 @@
+pkg
+gen2d
+gen3d
+docs
+target
+**/CHANGELOG.md
+**/README.md
\ No newline at end of file
diff --git a/typescript/.prettierrc b/typescript/.prettierrc
new file mode 100644
index 000000000..5a3e14301
--- /dev/null
+++ b/typescript/.prettierrc
@@ -0,0 +1,5 @@
+{
+ "tabWidth": 4,
+ "bracketSpacing": false,
+ "trailingComma": "all"
+}
diff --git a/typescript/CHANGELOG.md b/typescript/CHANGELOG.md
new file mode 100644
index 000000000..ef3052b96
--- /dev/null
+++ b/typescript/CHANGELOG.md
@@ -0,0 +1,937 @@
+## 0.19.3 (05 Nov. 2025)
+
+- Significantly improve performances of `combineVoxelStates`.
+
+### 0.19.2 (17 Oct. 2025)
+
+- Fix bug where kinematic bodies would not wake up when setting its velocity.
+- Fix bug where slow-moving kinematic bodies would fall asleep.
+- Fix point-projection on voxels shapes.
+
+### 0.19.1 (03 Oct. 2025)
+
+### Modified
+
+- Update to Rapier 0.30.0. The only change is a [switch to a sparse storage](https://github.com/dimforge/parry/pull/380)
+ for the Voxels shapes. This allows support for orders of magnitudes larger maps without reaching the 4GB WASM memory
+ limit.
+
+### 0.19.0 (05 Sept. 2025)
+
+### Modified
+
+- Update to Rapier 0.29.0 which includes performance improvements for scenes involving a lot of contact constraints.
+ See https://github.com/dimforge/rapier/pull/876 for details.
+- Renamed the `RigidBody.invPrincipalInertiaSqrt` and `.effectiveWorldInvInertiaSqrt` methods to
+ `RigidBody.invPrincipalInertia` and `.effectiveWorldInvInertia` (removed the `Sqrt` suffix). These methods will now
+ return the actual inverse angular inertia matrix rather than its square root.
+- Removed methods related to the legacy PGS solver: `World.numAdditionalFrictionIterations`,
+ `switchToStandardPgsSolver`, `switchToSmallStepsPgsSolver`, `switchToSmallStepsPgsSolverWithoutWarmstart`.
+
+### 0.18.2 (13 August 2025)
+
+### Fixed
+
+- Fix rollup configuration adding `types: "./rapier.d.ts"` to the export config.
+
+### 0.18.1 (8 August 2025)
+
+### Modified
+
+- Update to Rapier 0.28.0 which includes performance improvements when CCD is active and when
+ the user applies modification to a collider or rigid-body.
+
+### Fix
+
+- Another attempt to fix bundlerless module import with rapier-compat.
+
+### 0.18.0 (24 July 2025)
+
+### Added
+
+- Add `World.timing*` functions to access the internal performances measurements if the internal
+ profiler is enabled with `World.profilerEnabled = true`.
+- Add `World.maxCcdSubsteps` to get/set the max number of CCD substeps run by the engine.
+
+### Fix
+
+- Fixed crash that would happen when removing colliders in a particular order (e.g. in the same order
+ as their insertion).
+
+### 0.18.0-beta.0 (12 July 2025)
+
+#### Modified
+
+- Update to Rapier 0.27.0-beta.1 which includes a fully reworked broad-phase that supports scene queries.
+ This implies a performance gain on large scenes by avoiding the need to re-build the underlying acceleration
+ structure at each frame.
+- Un-deprecate methods for reading shape properties (for example `collider.radius()`). It turned out that these
+ methods are more convenient as they are guaranteed to always be in sync with rapier’s state on wasm.
+- Add `collider.translationWrtParent()` and `collider.rotationWrtParent()` to get the collider’s translation/rotation
+ relative to its parent rigid-body.
+
+#### Fix
+
+- rapier-compat top level javascript files extensions have been changed from `.cjs.js` and `.es.js` to `.cjs` and `mjs`
+ respectively. This results in better compatibility with NPM.
+
+### 0.17.3 (30 May 2025)
+
+#### Fix
+
+- The published package for 0.17.2 had a broken package.json. It is fixed on this release.
+
+### 0.17.2 (30 May 2025)
+
+#### Added
+
+- Added the function `RAPIER.reserveMemory` to instruct the internal allocator to pre-allocate more memory in preparation
+ for future operations. This typically called only once after initializing the WASM module.
+
+### 0.17.1 (23 May 2025)
+
+#### Added
+
+- Added optional arguments to `World.debugRender(filterFlags, filterPredicate)` to prevent some colliders from being
+ rendered.
+- Added `Collider.combineVoxelStates` to ensure two adjacent voxels colliders don’t suffer from the internal edges
+ problem, and `Collider.propagateVoxelChange` to maintain that coupling after modifications with `.setVoxel`.
+
+### 0.17.0 (16 May 2025)
+
+#### Fixed
+
+- Fix sensor events not triggering when hitting a voxels collider.
+
+#### Added
+
+- Added support for voxels colliders attached to dynamic rigid-bodies.
+- Added force calculation between colliding voxels/voxels and voxels/compound shapes.
+
+### 0.16.2 (5 May 2025)
+
+#### Fixed
+
+- Fixed infinite loop in `collider.setVoxel`.
+
+### 0.16.1 (2 May 2025)
+
+#### Added
+
+- Added `Collider.clearShapeCache` to release the reference to the JS shape stored in the collider, oor too force its
+ recomputation the next time the collider shape is accessed.
+- Added support for shape-casting involving Voxels colliders.
+- Added support for CCD involving Voxels colliders.
+
+### 0.16.0 (24 April 2025)
+
+#### Added
+
+- Added `ColliderDesc.voxels` to create a collider with a shape optimized for voxels.
+- Added `Collider.setVoxel` for adding or removing a voxel from a collider with a voxel shape.
+- Added the `Voxels` shape class.
+
+The support or voxels is still experimental. In particular the following features will currently **not** work on
+colliders with voxel shapes:
+
+- Voxels colliders attached to dynamic rigid-bodies will not run the automatic mass/angular inertia calculation.
+- Shape-casting on voxel shapes/colliders.
+- Collision-detection between two-voxels colliders, or a voxels collider and a mesh, polyline, or heightfield.
+
+See [parry#336](https://github.com/dimforge/parry/pull/336) for additional information.
+
+### 0.15.1 (10 April 2025)
+
+#### Added
+
+- Added `RigidBody.velocityAtPoint` function to retrieve the velocity of a given world-space point on a rigid-body.
+
+#### Modified
+
+- Update to Rapier 0.25. The main notable change is that the `TriMeshFlags.FIX_INTERNAL_EDGES` flag will no longer
+ imply that the `TriMeshFlags.ORIENTED` flag is set, avoiding edge-cases where enabling `FIX_INTERNAL_EDGES`
+ results in unexpected collisions between open meshes and balls.
+
+#### Fixed
+
+- Fixed `*-simd-compat` builds not actually emitting SIMD instructions.
+
+### 0.15.0 (06 March 2025)
+
+#### Added
+
+- Added `PidController`, `World.createPidController`, `World.removePidController` to create a Position-Integral-Derivative
+ controller; a building block for building velocity-based dynamic character controllers.
+
+#### Modified
+
+- Update to Rapier 0.24.
+- Package tree shaking has been disabled to avoid a crash on certain build configuration (#289).
+- Multiple packages with different feature sets are now released, and their build process has been automated (#309)
+ - Released packages are:
+ - rapier2d
+ - rapier2d-compat
+ - rapier2d-simd
+ - rapier2d-simd-compat
+ - rapier2d-deterministic
+ - rapier2d-deterministic-compat
+ - rapier3d
+ - rapier3d-compat
+ - rapier2d
+ - rapier2d-compat
+ - rapier3d-simd
+ - rapier3d-simd-compat
+ - rapier3d-deterministic
+ - rapier3d-deterministic-compat
+ - :warning: To this occasion, existing packages `rapier2d` and `rapier3d` are now built without `enhanced-determinism` feature enabled,
+ so if you rely on that feature, you should migrate to the new `-deterministic` flavor.
+
+
+### 0.14.0 (20 July 2024)
+
+#### Modified
+
+- Update from the rust library of rapier 0.19 to 0.22, see [rapier's changelog](https://github.com/dimforge/rapier/blob/master/CHANGELOG.md#v0210-23-june-2024) for more context.
+
+#### Added
+
+- Added `RigidBody.userForce` function to retrieve the constant force(s) the user added to a rigid-body
+- Added `RigidBody.userTorque` function to retrieve the constant torque(s) the user added to a rigid-body
+
+### 0.13.1 (2024-05-08)
+
+#### Fixed
+
+- Fix regression that could cause missed contact between a ball and another shape type.
+
+### 0.13.0 (2024-05-05)
+
+Several stability improvements are added as part of this release.
+See [rapier#625](https://github.com/dimforge/rapier/pull/625) for overviews of the most important improvements.
+
+#### Modified
+
+- The `castShape` and `castCollider` functions have been modified to add a `targetDistance` parameter. This parameter
+ indicates the distance below which a hit is detected.
+- Rename `RayIntersection.toi` to `.timeOfImpact` for better clarity.
+- Rename `RayColliderIntersection.toi` to `.timeOfImpact` for better clarity.
+- Rename `RayColliderToi` to `RayColliderHit`.
+- Rename `RayColliderHit.toi` to `.timeOfImpact` for better clarity.
+- Rename `ShapeTOI` to `ShapeCastHit`.
+- Rename `ShapeColliderTOI` to `ColliderShapeCastHit`.
+- Rename `ShapeCastHit.toi` to `.timeOfImpact`.
+
+#### Added
+
+- Fix the kinematic character controller getting stuck against vertical walls.
+- Add `KinematicCharacterController.normalNudgeFactor` and `.setNormalNudgeFactor` so set a coefficient used for
+ avoiding having the character controller get stuck on penetrations.
+- Add `RigidBody.softCcdPrediction`, `.setSoftCcdPrediction`, and `RigidBodyDesc.setSoftCcdPrediction` for configuring
+ soft-ccd on the rigid-body. See [rapier#625](https://github.com/dimforge/rapier/pull/625) for additional details on
+ soft-ccd.
+- 3D version only: add `TriMeshFlags::FIX_INTERNAL_EDGES` and `HeightFieldFlags::FIX_INTERNAL_EDGES` for enabling
+ internal edges correction (which is no longer enabled by default). The flags have been added as an optional parameter
+ when building the shapes.
+- Add `Collider.contactSkin`, `.setContactSkin`, and `ColliderDesc.setContactSkin` for configuring the collider’s
+ contact skin. See [rapier#625](https://github.com/dimforge/rapier/pull/625) for additional details on contact skins.
+- Add `World.lengthUnit` which can be used to indicate the typical size of dynamic objects (e.g. 100 pixels instead of
+ 1 meter). This helps the physics engine adjust internal thresholds for better results.
+
+#### Fixed
+
+- Fix an issue where the reported contact force are lower than their actual value.
+
+### 0.12.0 (2024-01-28)
+
+The main highlight of this release is the implementation of a new non-linear constraints solver for better stability
+and increased convergence rates. See [#579](https://github.com/dimforge/rapier/pull/579) for additional information.
+
+In order to adjust the number of iterations of the new solver, simply adjust `World.numSolverIterations`.
+If recovering the old solver behavior is useful to you, call `World.switchToStandardPgsSolver()`.
+
+It is now possible to specify some additional solver iteration for specific rigid-bodies (and everything interacting
+with it directly or indirectly through contacts and joints): `RigidBodyDesc.additionalSolverIterations` and
+`RigidBody::setAdditionalSolverIterations`. This allows for higher-accuracy on subsets of the physics scene
+without affecting performance of the other parts of the simulation.
+
+#### Modified
+
+- Renamed `CharacterController.translationApplied`, `.translationRemaining` and the `desiredTranslation`
+ method argument to `CharacterController.translationDeltaApplied`, `.translationDeltaRemaining` and the
+ `desiredTranslationDelta` to avoid confusion with the usage of the `translation` world in `RigidBody.translation()`.
+
+#### Added
+
+- Added `DynamicRayCastVehicleController` to simulate vehicles based on ray-casting.
+- Added `JointData.generic` (3D only) to create a generic 6-dof joint and manually specify the locked axes.
+
+### 0.11.2
+
+#### Fixed
+
+- Fix bug that made dynamic rigid-bodies behave like kinematic bodies after being disabled and then re-enabled.
+- Fix issue with convex polyhedron jitter due to missing contacts.
+- Fix character controller getting stuck against vertical walls.
+- Fix character controller’s snapping to ground not triggering sometimes.
+- Fix character controller’s horizontal offset being mostly ignored and some instances of vertical offset being ignored.
+
+#### Added
+
+- Add `JointData.spring` and `JointData.rope` joints.
+- Add access to the mass-properties of a rigid-body: `RigidBody.effectiveInvMass`, `.invMass()`, `.localCom()`,
+ `.worldCom()`, `.invPrincipalInertiaSqrt()`, `.principalInertia()`, `.principalInertiaLocalFrame()`,
+ `.effectiveWorldInvInertiaSqrt()`, `.effectiveAngularInertia()`.
+- Add `DynamicRayCastVehicleController.siteFrictionStiffness` to customize the side friction applied to the vehicle
+ controller’s wheel.
+
+#### Modified
+
+- Rename `World.contactsWith` to `World.contactPairsWith`.
+- Rename `World.intersectionsWith` to `World.intersectionPairsWith`.
+
+### 0.11.1 (2023-01-16)
+
+#### Fixed
+
+- Fix bug that disabled all colliders at construction time.
+
+### 0.11.0 (2023-01-15)
+
+#### Added
+
+- Add `World.propagateModifiedBodyPositionsToColliders` to propagate rigid-bodies position changes to their attached
+ colliders.
+- Add `World.updateSceneQueries` to update the scene queries data structures without stepping the whole simulation.
+- Add `RigidBody.isEnabled, RigidBody.setEnabled, RigidBodyDesc.setEnabled` to disable a rigid-body (and all its
+ attached colliders) without removing it from the physics world.
+- Add `Collider.isEnabled, Collider.setEnabled, ColliderDesc.setEnabled` to disable a collider without removing it
+ from the physics world.
+- Add shape-specific methods to modify a collider’s
+ size: `Collider.setRadius, setHalfExtents, setRoundRadius, setHalfHeight`.
+
+#### Modified
+
+- Add a boolean argument to `RigidBody.setBodyType` to indicate if the rigid-body should awaken after changing
+ its type.
+
+#### Fixed
+
+- Fix rigid-bodies automatically waking up at creation even if they were explicitly created sleeping.
+
+### 0.10.0 (2022-11-06)
+
+#### Added
+
+- Add `World.createCharacterController`, `World.removeCharacterController` to create/remove a kinematic character
+ controller.
+- Add a character-controller implementation with the `KinematicCharacterController` class and its method
+ `KinematicCharacterController.computeColliderMovement`. The character controller features currently supported are:
+ - Slide on uneven terrains
+ - Interaction with dynamic bodies.
+ - Climb stairs automatically.
+ - Automatically snap the body to the floor when going downstairs.
+ - Prevent sliding up slopes that are too steep
+ - Prevent sliding down slopes that are not steep enough
+ - Interactions with moving platforms.
+ - Report information on the obstacles it hit on its path.
+- Add the `HalfSpace` (infinite plane) shape. Colliders with this shape can be built using `ColliderDesc.halfspace`.
+
+#### Modified
+
+- Change the signature of `Collider.castShape` and World.castShape by adding a boolean argument `stop_at_penetration`
+ before the filter-related arguments. Set this argument to `true` to get the same result as before. If this is set to
+ `false` and the shape being cast starts it path already intersecting another shape, then a hit won’t be returned
+ with that intersecting shape unless the casting movement would result in more penetrations.
+- Reduce rounding errors in 3D when setting the rotation of a rigid-body or collider.
+
+#### Fixed
+
+- Fix incorrect application of torque if the torque is applies right after setting the rigid-body’s
+ position, but before calling `World.step`.
+
+### 0.9.0 (2022-10-07)
+
+#### Fixed
+
+- Fix unpredictable broad-phase panic when using small colliders in the simulation.
+- Fix collision events being incorrectly generated for any shape that produces multiple
+ contact manifolds (like triangle meshes).
+
+#### Modified
+
+- The `RigidBodyDesc.setAdditionalMass` method will now result in the additional angular inertia
+ being automatically computed based on the shapes of the colliders attached to the rigid-body.
+- Removed the method `RigidBodyDesc.setAdditionalPrincipalAngularInertia`. Use
+ `RigidBodyDesc.setAdditionalMassProperties` instead.
+- The methods of `RigidBodyDesc` and `ColliderDesc` will now always copy the object provided by
+ the user instead of storing the object itself.
+- The following method will now copy the user’s objects instead of storing it: `ColliderDesc.setRotation`,
+ `ColliderDesc.setMassProperties`, `RigidBodyDesc.setRotation`, `RigidBodyDesc.setAdditionalMassProperties`,
+ `RigidBodyDesc.setAngvel`.
+- Rename `RigidBody.restrictRotations` and `RigidBody.restrictTranslations` to
+ `RigidBody.setEnabledRotations` and `RigidBody.setEnabledTranslations`.
+- Rename `RigidBodyDesc.restrictRotations` and `RigidBodyDesc.restrictTranslations` to
+ `RigidBodyDesc.enabledRotations` and `RigidBodyDesc.enabledTranslations`.
+
+#### Added
+
+- Add `ImpulseJoint.setContactsEnabled`, and `MultibodyJoint.setContactsEnabled` to set whether
+ contacts are enabled between colliders attached to rigid-bodies linked by this joint.
+- Add `UnitImpulseJoint.setLimits` to set the limits of a unit joint.
+- Add `RigidBody.recomputeMassPropertiesFromColliders` to force the immediate computation
+ of a rigid-body’s mass properties (instead of waiting for them to be recomputed during the next
+ timestep). This is useful to be able to read immediately the result of a change of a rigid-body
+ additional mass-properties or a change of one of its collider’s mass-properties.
+- Add `RigidBody::setAdditionalMass` to set the additional mass for the rigid-body. The additional
+ angular inertia is automatically computed based on the attached colliders shapes. If this automatic
+ angular inertia computation isn’t desired, use `RigidBody::setAdditionalMassProperties` instead.
+- Add `Collider.setDensity`, `.setMass`, `.setMassProperties`, to alter a collider’s mass
+ properties. Note that `.setMass` will result in the collider’s angular inertia being automatically
+ computed based on this mass and on its shape.
+- Add `ColliderDesc.setMass` to set the mass of the collider instead of its density. Its angular
+ inertia tensor will be automatically computed based on this mass and its shape.
+- Add more filtering options for scene-queries. All the scene query methods now take additional optional
+ arguments to indicate if one particular collider, rigid-body, or type of colliders/rigid-bodies have to
+ be ignored by the query.
+- Add force reporting based on contact force events. The `EventHandler` trait has been modified to include
+ the method `EventQueue.drainContactForceEvents`. Contact force events are generated whenever the sum of the
+ magnitudes of all the forces between two colliders is greater than any of their
+ `Collider.contactForceEventThreshold` values (only the colliders with the `ActiveEvents.CONTACT_FORCE_EVENT`
+ flag set are taken into account for this threshold).
+
+### 0.8.1 (2022-04-06)
+
+Starting with this release, all the examples in `testbed2d` and `testbed3d` have been updated to `webpack 5`,
+and are written in Typescript. In addition, canary `0.0.0` releases will be generated automatically after each merge
+to the `master` branch.
+
+#### Fixed
+
+- Fix bug causing `World.intersectionPair` to always return `false`.
+
+### 0.8.0 (2022-03-31)
+
+#### Breaking changes
+
+- Most APIs that relied on rigid-body handles or collider handles have been modified to rely on `RigidBody`
+ or `Collider` objects instead. Handles are now only needed for events and hooks.
+- Rename STATIC to FIXED in the `ActiveCollisionTypes` flags.
+- The `RigidBody.applyForce` and `.applyTorque` methods have been replaced by `.addForce` and `.addTorque`. These
+ force/torques are no longer automatically zeroed after a timestep. To zero them manually, call `.resetForce` or
+ `.resetTorque`.
+- The `EventQueue.drainContactEvents` and `EventQueue.drainIntersectionEvents` have been merged into a single
+ method: `EventQueue:drainCollisionEvents`.
+
+#### Added
+
+- Add a lines-based debug-renderer. See [#119](https://github.com/dimforge/rapier.js/pull/119) for examples of
+ integration of the debug-renderer with `THREE.js` and `PIXI.js`.
+- Each rigid-body, collider, impulse joint, and multibody joint now have a unique object instance. This instance
+ in only valid as long as the corresponding objects is inserted to the `World`.
+- Add a `wakeUp: bool` argument to the `World.createImpulseJoint` and `MultibodyJointSet::createMultibodyJoint` to
+ automatically wake-up the rigid-bodies attached to the inserted joint.
+- Add a `filter` callback to all the scene queries. Use this for filtering more fine-grained than collision groups.
+- Add `collider.shape` that represents the shape of a collider. This is a more convenient way of reading the collider’s
+ shape properties. Modifying this shape will have no effect unless `collider.setShape` is called with the modified
+ shape.
+- Add `Collider.containsPoint`, `.projectPoint`, `.intersectsRay`, `.castShape`, `.castCollider`, `.intersectsShape`,
+ `.contactShape`, `.contactCollider`, `.castRay`, `.castRayAndGetNormal`.
+- Add `Shape.containsPoint`, `.projectPoint`, `.intersectsRay`, `.castShape`, `.intersectsShape`,
+ `.contactShape`, `.castRay`, `.castRayAndGetNormal`.
+- Add `World.projectPointAndGetFeature` which includes the feature Id the projected point lies on.
+- Add `RigidBodyDesc.sleeping` to initialize the rigid-body in a sleeping state.
+
+### 0.8.0-alpha.2 (2022-03-20)
+
+The changelog hasn’t been updated yet.
+For an overview of the changes, refer to the changelog for the unreleased Rust version:
+https://github.com/dimforge/rapier/blob/master/CHANGELOG.md#unreleased
+
+### 0.8.0-alpha.1 (2022-01-28)
+
+#### Fixed
+
+- Fix a crash when calling `collider.setShape`.
+- Fix a crash when calling `world.collidersWithAabbIntersectingAabb`.
+- Fix damping not being applied properly to some rigid-bodies.
+
+### 0.8.0-alpha.0 (2022-01-16)
+
+This release updates to Rapier 0.12.0-alpha.0 which contains:
+
+- A **complete rewrite** of the joint and contact constraint solver.
+- The support for locking individual translation axes.
+- The support for multibody joint.
+
+This is an **alpha** release because the new solver still needs some tuning,
+and the spherical joint motors/limits is currently not working.
+
+#### Breaking changes
+
+- In 3D: renamed `BallJoint` to `SphericalJoint`.
+- In 2D: renamed `BallJoint` to `RevoluteJoint`.
+- Remove the joint motors and limits for the spherical joint (this is a temporary removal until with leave alpha).
+- All the joint-related structures and methods (`RevoluteJoint`, `PrismaticJoint`, `createJoint`, etc.) have renamed to
+ include `impulse` in the names: `RevoluteImpulseJoint`, `PrismaticImpulseJoint`, `createImpulseJoint`, etc. This is
+ to differentiate them from the new multibody joints.
+- Remove from the integration parameters all the parameters that are no longer meaningful (`maxPositionIterations`,
+ `jointErp`, `warmstartCoeff`, `allowedAngularError`, `maxLinearCorrection`, `maxAngularCorrection`).
+
+#### Added
+
+- Add multibody joints. They are created the same way as impulse joints, except that they are created
+ by `world.createMultibodyJoint` instead of `world.createImpulseJoint`.
+- Add the ability to lock individual translation axes. Use `rigidBody.restrictTranslation`.
+
+#### Fixed
+
+- Fixed an issue with velocity-based kinematic bodies applying kinematic rotation improperly.
+- Fixed the second witness points and normals returned by shape-casts.
+- Fixed the second local contact normal and points returned by contact manifolds.
+
+### 0.7.6
+
+This release updates to Rapier 0.11.1 which contains several bug fixes.
+
+#### Fixed
+
+- Fix a bug causing large moving colliders to miss some collisions after some time.
+- Fix invalid forces generated by contacts with position-based kinematic bodies.
+- Fix a bug where two colliders without parent would not have their collision computed even if the
+ appropriate flags were set.
+
+### 0.7.5
+
+#### Fixed
+
+- Fixed an issue where a collider with no parent attached would not be created
+ under some conditions.
+
+### 0.7.4
+
+This release was broken and has been unpublished.
+
+### 0.7.3
+
+#### Fixed
+
+- The `collider.halfExtents()` methods now returns a valid value for round cuboids.
+
+### 0.7.2 (rapier-compat only)
+
+#### Modified
+
+- The `rapier-compat` packages don’t need the `Buffer` polyfill anymore.
+
+### 0.7.1
+
+#### Modified
+
+- Update to use Rapier 0.11.0.
+- The `rapier-compat` packages are now generated by rollup.
+
+### v0.7.0
+
+The typescripts bindings for Rapier have
+a [brand new user-guide](https://rapier.rs/docs/user_guides/javascript/getting_started_js)
+covering all the features of the physics engine!
+
+### Breaking change
+
+- The `World.castRay` and `World.castRayAndGetNormal` methods have a different signature now, making them
+ more flexible.
+- Rename `ActiveHooks::FILTER_CONTACT_PAIR` to `ActiveHooks.FILTER_CONTACT_PAIRS`.
+- Rename `ActiveHooks::FILTER_INTERSECTION_PAIR` to `ActiveHooks.FILTER_INTERSECTION_PAIRS`.
+- Rename `BodyStatus` to `RigidBodyType`.
+- Rename `RigidBody.bodyStatus()` to `RigidBody.bodyType()`.
+- Rename `RigidBodyDesc.setMassProperties` to `RigidBodyDesc.setAdditionalMassProperties`.
+- Rename `RigidBodyDesc.setPrincipalAngularInertia` to `RigidBodyDesc.setAdditionalPrincipalAngularInertia`.
+- Rename `ColliderDesc.setIsSensor` to `ColliderDesc.setSensor.
+
+#### Added
+
+- Add `Ray.pointAt(t)` that conveniently computes `ray.origin + ray.dir * t`.
+- Add access to joint motors by defining each joint with its own class deriving from `Joint`. Each joint now
+ have its relevant motor configuration
+ methods: `configurMotorModel, configureMotorVelocity, configureMotorPosition, configureMotor`.
+- Add `World.collidersWithAabbIntersectingAabb` for retrieving the handles of all the colliders intersecting the given
+ AABB.
+- Add many missing methods for reading/modifying a rigid-body state after its creation:
+ - `RigidBody.lockTranslations`
+ - `RigidBody.lockRotations`
+ - `RigidBody.restrictRotations`
+ - `RigidBody.dominanceGroup`
+ - `RigidBody.setDominanceGroup`
+ - `RigidBody.enableCcd`
+- Add `RigidBodyDesc.setDominanceGroup` for setting the dominance group of the rigid-body being built.
+- Add many missing methods for reading/modifying a collider state after its creation:
+ - `Collider.setSendor`
+ - `Collider.setShape`
+ - `Collider.setRestitution`
+ - `Collider.setFriction`
+ - `Collider.frictionCombineRule`
+ - `Collider.setFrictionCombineRule`
+ - `Collider.restitutionCombineRule`
+ - `Collider.setRestitutionCombineRule`
+ - `Collider.setCollisionGroups`
+ - `Collider.setSolverGroups`
+ - `Collider.activeHooks`
+ - `Collider.setActiveHooks`
+ - `Collider.activeEvents`
+ - `Collider.setActiveEvents`
+ - `Collider.activeCollisionTypes`
+ - `Collider.setTranslation`
+ - `Collider.setTranslationWrtParent`
+ - `Collider.setRotation`
+ - `Collider.setRotationWrtParent`
+- Add `ColliderDesc.setMassProperties` for setting explicitly the mass properties of the collider being built (instead
+ of relying on density).
+
+#### Modified
+
+- Colliders are no longer required to be attached to a rigid-body. Therefore, the second argument
+ of `World.createCollider`
+ is now optional.
+
+### v0.6.0
+
+#### Breaking changes
+
+- The `BodyStatus::Kinematic` variant has been replaced by `BodyStatus::KinematicPositionBased` and
+ `BodyStatus::KinematicVelocityBased`. Position-based kinematic bodies are controlled by setting (at each frame) the
+ next
+ kinematic position of the rigid-body (just like before), and the velocity-based kinematic bodies are controlled
+ by setting (at each frame) the velocity of the rigid-body.
+- The `RigidBodyDesc.newKinematic` has been replaced by `RigidBodyDesc.newKinematicPositionBased` and
+ `RigidBodyDesc.newKinematicVelocityBased` in order to build a position-based or velocity-based kinematic body.
+- All contact and intersection events are now disabled by default. The can be enabled for each collider individually
+ by setting
+ its `ActiveEvents`: `ColliderDesc.setActiveEvents(ActiveEvents.PROXIMITY_EVENTS | ActiveEvents.ContactEvents)`.
+
+#### Added
+
+- It is now possible to read contact information from the narrow-phase using:
+ - `world.narrowPhase.contactsWith(collider1, callback)`
+ - `world.narrowPhase.intersectionsWith(collider1, callback)`
+ - `world.narrowPhase.contactPair(collider1, collider2, callback)`
+ - `world.narrowPhase.intersectionPair(collider1, collider2, callback)`
+- It is now possible to apply custom collision-detection filtering rules (more flexible than collision groups)
+ based on a JS object by doing the following:
+ - Enable physics hooks for the colliders you want the custom rules to apply to:
+ `ColliderDesc.setActiveHooks(ActiveHooks.FILTER_CONTACT_PAIR | ActiveHooks.FILTER_CONTACT_PAIR)`
+ - Define an object that implements the `PhysicsHooks` interface.
+ - Pass and instance of your physics hooks object as the second argument of the `World.step` method.
+- It is now possible to enable collision-detection between two non-dynamic bodies (e.g. between a kinematic
+ body and a fixed body) by setting the active collision types of a collider:
+ `ColliderDesc.setActiveCollisionTypes(ActiveCollisionTypes.ALL)`
+
+### v0.5.3
+
+- Fix a crash when loading the WASM file on iOS safari.
+
+### v0.5.2
+
+- Fix a crash that could happen after adding and then removing a collider right away,
+ before stepping the simulation.
+
+### v0.5.1
+
+- Fix a determinism issue after snapshot restoration.
+
+### v0.5.0
+
+- Significantly improve the broad-phase performances when very large colliders are used.
+- Add `RigidBodyDesc::setCcdEnabled` to enable Continuous Collision Detection (CCD) for this rigid-body. CCD ensures
+ that a fast-moving rigid-body doesn't miss a collision (the tunneling problem).
+
+#### Breaking changes:
+
+- Removed multiple fields from `IntegrationParameters`. These were unused parameters.
+
+### v0.4.0
+
+- Fix a bug in ball/convex shape collision detection causing the ball to ignore penetrations with depths greater than
+ its radius.
+
+Breaking changes:
+
+- Removed `IntegrationParameters.restitutionVelocityThreshold`
+ and `IntegrationParameters.set_restitutionVelocityThreshold`.
+
+### v0.3.1
+
+- Fix crash happening when creating a collider with a `ColliderDesc.convexHull` shape.
+- Actually remove the second argument of `RigidBodyDesc.setMass` as mentioned in the 0.3.0 changelog.
+- Improve snapshotting performances.
+
+### v0.3.0
+
+#### Added
+
+- Added a `RAPIER.version()` function at the root of the package to retrieve the version of Rapier as a string.
+
+Several geometric queries have been added (the same methods have been added to the
+`QueryPipeline` too):
+
+- `World.intersectionsWithRay`: get all colliders intersecting a ray.
+- `World.intersectionWithShape`: get one collider intersecting a shape.
+- `World.projectPoint`: get the projection of a point on the closest collider.
+- `World.intersectionsWithPoint`: get all the colliders containing a point.
+- `World.castShape`: get the first collider intersecting a shape moving linearly
+ (aka. sweep test).
+- `World.intersectionsWithShape`: get all the colliders intersecting a shape.
+
+Several new shape types are now supported:
+
+- `RoundCuboid`, `Segment`, `Triangle`, `RoundTriangle`, `Polyline`, `ConvexPolygon` (2D only),
+ `RoundConvexPolygon` (2D only), `ConvexPolyhedron` (3D only), `RoundConvexPolyhedron` (3D only),
+ `RoundCone` (3D only).
+
+It is possible to build `ColliderDesc` using these new shapes:
+
+- `ColliderDesc.roundCuboid`, `ColliderDesc.segment`, `ColliderDesc.triangle`, `ColliderDesc.roundTriangle`,
+ `ColliderDesc.convexHull`, `ColliderDesc.roundConvexHull`, `ColliderDesc.Polyline`,
+ `ColliderDesc.convexPolyline` (2D only), `ColliderDesc.roundConvexPolyline` (2D only),
+ `ColliderDesc.convexMesh` (3D only),`ColliderDesc.roundConvexMesh` (3D only), `ColliderDesc.roundCone` (3D only).
+
+It is possible to specify different rules for combining friction and restitution coefficients of the two colliders
+involved in a contact with:
+
+- `ColliderDesc.frictionCombineRule`, and `ColliderDesc.restitutionCombineRule`.
+
+Various RigidBody-related getter and setters have been added:
+
+- `RigidBodyDesc.newStatic`, `RigidBodyDesc.newDynamic`, and `RigidBodyDesc.newKinematic` are new static method, short
+ equivalent to `new RigidBodyDesc(BodyStatus.Static)`, etc.
+- `RigidBodyDesc.setGravityScale`, `RigidBody.gravityScale`, `RigidBody.setGravityScale` to get/set the scale factor
+ applied to the gravity affecting a rigid-body. Setting this to 0.0 will make the rigid-body ignore gravity.
+- `RigidBody.setLinearDamping` and `RigidBody.setAngularDamping` to set the linear and angular damping of the
+ rigid-body.
+- `RigidBodyDesc.restrictRotations` to prevent rotations along specific coordinate axes. This replaces the three boolean
+ arguments previously passed to `.setPrincipalAngularInertia`.
+
+#### Breaking changes
+
+Breaking changes related to rigid-bodies:
+
+- The `RigidBodyDesc.setTranslation` and `RigidBodyDesc.setLinvel` methods now take the components of the translation
+ directly as arguments instead of a single `Vector`.
+- The `RigidBodyDesc.setMass` takes only one argument now. Use `RigidBodyDesc.lockTranslations` to lock the
+ translational motion of the rigid-body.
+- The `RigidBodyDesc.setPrincipalAngularInertia` no longer have boolean parameters to lock rotations.
+ Use `RigidBodyDesc.lockRotations` or `RigidBodyDesc.restrictRotations` to lock the rotational motion of the
+ rigid-body.
+
+Breaking changes related to colliders:
+
+- The `ColliderDesc.setTranslation` method now take the components of the translation directly as arguments instead of a
+ single `Vector`.
+- The `roundRadius` fields have been renamed `borderRadius`.
+- The `RawShapeType.Polygon` no longer exists. For a 2D convex polygon, use `RawShapeType.ConvexPolygon`
+ instead.
+- All occurrences of `Trimesh` have been replaced by `TriMesh` (note the change in case).
+
+Breaking changes related to events:
+
+- Rename all occurrences of `Proximity` to `Intersection`.
+- The `Proximity` enum has been removed.
+- The `drainIntersectionEvents` (previously called `drainProximityEvent`) will now call a callback with
+ arguments `(number, number, boolean)`: two collider handles, and a boolean indicating if they are intersecting.
+
+Breaking changes related to scene queries:
+
+- The `QueryPipeline.castRay` method now takes two additional parameters: a boolean indicating if the ray should not
+ propagate if it starts inside of a shape, and a bit mask indicating the group the ray is part of and these it
+ interacts with.
+- The `World.castRay` and `QueryPipeline.castRay` now return a struct of type `RayColliderHit`
+ which no longer contains the normal at the hit point. Use the new methods `World.castRayAndGetNormal`
+ or `QueryPipeline.castRayAndGetNormal` in order to retrieve the normal too.
+
+### v0.2.13
+
+- Fix a bug where `RigidBodyDesc.setMass(m)` with `m != 0.0` would cause the rotations of the created rigid-body to be
+ locked.
+
+### v0.2.12
+
+- Add a boolean argument to `RigidBodyDesc.setMass` to indicate if the mass contribution of colliders should be enabled
+ for this rigid-body or not.
+- Add a `RigidBody.lockRotations` method to lock all the rigid-body rotations resulting from forces.
+- Add a `RigidBody.lockTranslations` method to lock all the rigid-body translations resulting from forces.
+- Add a `RigidBody.setPrincipalAngularInertia` method to set the principal inertia of the rigid-body. This gives the
+ ability to lock individual rotation axes of one rigid-body.
+
+### v0.2.11
+
+- Fix a bug where removing when immediately adding a collider would cause collisions to fail with the new collider.
+- Fix a regression causing some colliders added after a few timesteps not to be properly taken into account.
+
+### v0.2.10
+
+- Fix a bug where removing a collider would result in a rigid-body being removed instead.
+- Fix a determinism issue when running simulation on the Apple M1 processor.
+- Add `JointData.prismatic` and `JointData.fixed` for creating prismatic joint or fixed joints.
+
+### v0.2.9
+
+- Add `RigidBody.setLinvel` to set the linear velocity of a rigid-body.
+- Add `RigidBody.setAngvel` to set the angular velocity of a rigid-body.
+
+### v0.2.8
+
+- Add `RigidBodySet.remove` to remove a rigid-body from the set.
+- Add `ColliderSet.remove` to remove a collider from the set.
+- Add `JointSet.remove` to remove a joint from the set.
+- Add `RigidBodyDesc.setLinearDamping` and `RigidBodyDesc.setAngularDamping` for setting the linear and angular damping
+ coefficient of the rigid-body to create.
+- Add `RigidBodyDesc.setMass`, and `RigidBodyDesc.setMassProperties` for setting the initial mass properties of a
+ rigid-body.
+- Add `ColliderDesc.setCollisionGroups` to use bit-masks for collision filtering between some pairs of colliders.
+- Add `ColliderDesc.setSolverGroups` to use bit-masks for making the constraints solver ignore contacts between some
+ pairs of colliders.
+- Add `ColliderDesc.heightfield` to build a collider with an heightfield shape.
+- Add `ColliderDesc.trimesh` to build a collider with a triangle mesh shape.
+
+### v0.2.7
+
+- Reduce snapshot size and computation times.
+
+### v0.2.6
+
+- Fix bug causing an unbounded memory usage when an objects falls indefinitely.
+
+### v0.2.5
+
+- Fix wrong result given by `RigidBody.isKinematic()` and `RigidBody.isDynamic()`.
+
+### v0.2.4
+
+- Add the support for round cylinder colliders (i.e. cylinders with round edges).
+
+### v0.2.3
+
+- Add the support for cone, cylinder, and capsule colliders.
+
+### v0.2.2
+
+- Fix regression causing the density and `isSensor` properties of `ColliderDesc` to not be taken into account.
+- Throw an exception when the parent handle passed to `world.createCollider` is not a number.
+
+### v0.2.1
+
+This is a significant rewrite of the JavaScript bindings for rapier. The objective of this rewrite is to make the API
+closer to Rapier's and remove most need for manual memory management.
+
+- Calling `.free()` is now required only for objects that live for the whole duration of the simulation. This means that
+ it is no longer necessary to `.free()` vectors, rays, ray intersections, colliders, rigid-bodies, etc. Object that
+ continue to require an explicit `.free()` are:
+ - `World` and `EventQueue`.
+ - Or, if you are not using the `World` directly:
+ `RigidBodySet`, `ColliderSet`, `JointSet`, `IntegrationParameters`, `PhysicsPipeline`, `QueryPipeline`
+ , `SerializationPipeline`, and `EventQueue`.
+- Collider.parent() now returns the `RigidBodyHandle` of its parent (instead of the `RigidBody` directly).
+- Colliders are now built with `world.createCollider`, i.e., `body.createCollider(colliderDesc)`
+ becomes `world.createCollider(colliderDesc, bodyHandle)`.
+- Shape types are not an enumeration instead of strings: `ShapeType.Ball` and `ShapeType.Cuboid` instead of `"ball"`
+ and `"cuboid"`.
+- `collider.handle` is now a field instead of a function.
+- `body.handle` is now a field instead of a function.
+- The world's gravity is now a `Vector` instead of individual components, i.e., `let world = new RAPIER.World(x, y, z);`
+ becomes `let world = new RAPIER.World(new RAPIER.Vector3(x, y, z))`.
+- Most methods that took individual components as argument (`setPosition`, `setKinematicPosition`, `setRotation`, etc.)
+ now take a `Vector` or `Rotation` structure instead. For example `rigid_body.setKinematicPosition(x, y, z)`
+ becomes `rigid_body.setKinematicPosition(new RAPIER.Vector3(x, y, z))`.
+- `world.stepWithEvents` becomes `world.step` (the event queue is the last optional argument).
+- `RigidBodyDesc` and `ColliderDesc` now use the builder pattern. For example
+ `let bodyDesc = new RAPIER.RigidBodyDesc("dynamic"); bodyDesc.setTranslation(x, y, z)` becomes
+ `new RigidBodyDesc(BodyStatus.Dynamic).setTranslation(new Vector(x, y, z))`.
+- `ray.dir` and `ray.origin` are now fields instead of methods.
+- 2D rotations are now just a `number` instead of a `Rotation` struct. So instead of doing `rotation.angle`, single use
+ the number as the rotation angle.
+- 3D rotations are now represented by the interface `Rotation` (with fields `{x,y,z,w}`) or the class `Quaternion`. Any
+ object with these `{x, y, z, w}` fields can be used wherever a `Rotation` is required.
+- 2D vectors are now represented by the interface `Vector` (with fields `{x,y}`) or the class `Vector2`). Any object
+ with these `{x,y}` fields can be used wherever a `Vector` is required.
+- 3D vectors are now represented by the interface `Vector` (with fields `{x,y,z}`) or the class `Vector3`). Any object
+ with these `{x,y,z}` fields can be used wherever a `Vector` is required.
+
+### v0.2.0
+
+See changelogs for v0.2.1 instead. The NPM package for v0.2.0 were missing some files.
+
+### v0.1.17
+
+- Fix bug when ghost forces and/or crashes could be observed when a kinematic body touches a fixed body.
+
+### v0.1.16
+
+- Fix kinematic rigid-body not waking up dynamic bodies it touches.
+- Added `new Ray(origin, direction)` constructor instead of `Ray.new(origin, direction)`.
+
+### v0.1.15
+
+- Fix crash when removing a kinematic rigid-body from the World.
+
+### v0.1.14
+
+- Fix issues where force application functions took ownership of the JS vector, preventing the user from freeing
+ with `Vector.free()` afterwards.
+
+### v0.1.13
+
+- Added `rigidBody.setNextKinematicTranslation` to set the translation of a kinematic rigid-body at the next timestep.
+- Added `rigidBody.setNextKinematicRotation` to set the rotation of a kinematic rigid-body at the next timestep.
+- Added `rigidBody.predictedTranslation` to get the translation of a kinematic rigid-body at the next timestep.
+- Added `rigidBody.predictedRotation` to set the rotation of a kinematic rigid-body at the next timestep.
+- Added `Ray` and `RayIntersection` structures for ray-casting.
+- Added `world.castRay` to compute the first hit of a ray with the physics scene.
+- Fix a bug causing a kinematic rigid-body not to teleport as expected after a `rigidBody.setPosition`.
+
+### v0.1.12
+
+- Added `world.removeCollider(collider)` to remove a collider from the physics world.
+- Added `colliderDesc.setTranslation(...)` to set the relative translation of the collider to build wrt. the rigid-body
+ it is attached to.
+- Added `colliderDesc.setRotation(...)` to set the relative rotation of the collider to build wrt. the rigid-body it is
+ attached to.
+
+### v0.1.11
+
+- Fix a bug causing a crash when the broad-phase proxy handles were recycled.
+
+### v0.1.10
+
+- Fix a determinism problem that could cause rigid-body handle allocation to be non-deterministic after a snapshot
+ restoration.
+
+### v0.1.9
+
+- Added `world.getCollider(handle)` that retrieves a collider from its integer handle.
+- Added `joint.handle()` that returns the integer handle of the joint.
+
+### v0.1.8
+
+- Added `world.forEachRigidBodyHandle(f)` to apply a closure on the integer handle of each rigid-body on the world.
+- Added `world.forEachActiveRigidBody(f)` to apply a closure on each rigid-body on the world.
+- Added `world.forEachActiveRigidBodyHandle(f)` to apply a closure on the integer handle of each rigid-body on the
+ world.
+- Added `rigidBody.applyForce`, `.applyTorque`, `.applyImpulse`, `.applyTorqueImpulse`, `.applyForceAtPoint`, and
+ `.applyImpulseAtPoint` to apply a manual force or torque to a rigid-body.
+- Added the `EventQueue` structure that can be used to collect and iterate through physics events.
+- Added the `Proximity` enum that represents the proximity state of a sensor collider and another collider.
+- Added the `world.stepWithEvents(eventQueue)` which executes a physics timestep and collects the physics events into
+ the given event queue.
+
+### v0.1.7
+
+- Added `world.getRigidBody(handle)` to retrieve a rigid-body from its handle.
+- Added `world.getJoint(handle)` to retrieve a joint from its handle.
+- Added `rigidBody.rotation()` to retrieve its world-space orientation as a quaternion.
+- Added `rigidBody.setTranslation(...)` to set the translation of a rigid-body.
+- Added `rigidBody.setRotation(...)` to set the orientation of a rigid-body.
+- Added `rigidBody.wakeUp()` to manually wake up a rigid-body.
+- Added `rigidBody_desc.setRotation(...)` to set tho orientation of the rigid-body to be created.
+
+### v0.1.6
+
+- Added `world.removeRigidBody(...)` to remove a rigid-body from the world.
diff --git a/typescript/Cargo.toml b/typescript/Cargo.toml
new file mode 100644
index 000000000..6b4d76565
--- /dev/null
+++ b/typescript/Cargo.toml
@@ -0,0 +1,26 @@
+[workspace]
+members = ["builds/*"]
+resolver = "2"
+
+[profile.release]
+debug = false
+codegen-units = 1
+#lto = true
+strip = true # Workaround for https://github.com/bevyengine/bevy/issues/16030 (the bug only happens in 2D)
+
+[patch.crates-io]
+# Build the JS/Wasm bindings against the rapier crates in this repository rather
+# than the versions published on crates.io, so the bindings always stay in sync
+# with the engine they ship alongside. The build crates' `rapier{2,3}d`
+# dependency requirement (see builds/prepare_builds/templates/Cargo.toml.tera)
+# must stay semver-compatible with the in-repo crate version for this to apply.
+rapier2d = { path = "../crates/rapier2d" }
+rapier3d = { path = "../crates/rapier3d" }
+
+# parry, nalgebra and simba are still pulled from crates.io, matching the
+# versions the in-repo rapier crates depend on. Uncomment to build against local
+# checkouts placed next to this repository during development.
+#parry2d = { path = "../../parry/crates/parry2d" }
+#parry3d = { path = "../../parry/crates/parry3d" }
+#nalgebra = { path = "../../nalgebra" }
+#simba = { path = "../../simba" }
diff --git a/typescript/LICENSE b/typescript/LICENSE
new file mode 100644
index 000000000..e579674df
--- /dev/null
+++ b/typescript/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2020 Dimforge EURL
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/typescript/README.md b/typescript/README.md
new file mode 100644
index 000000000..d04cc4bf4
--- /dev/null
+++ b/typescript/README.md
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Website | Documentation |
+ 2D examples (sources) |
+ 3D examples (sources)
+
+
+
+---
+
+
+2D and 3D physics engines
+for the JavaScript programming language (official bindings).
+
+
+---
+
+## Building packages manually
+
+From the root of the repository, run:
+
+```shell
+./builds/prepare_builds/prepare_all_projects.sh
+./builds/prepare_builds/build_all_projects.sh
+```
+
+Note that `prepare_all_projects.sh` only needs to be run once. It needs to be re-run if any file from the
+`builds/prepare_builds` directory (and subdirectories) are modified.
+
+The built packages will be in `builds/rapier2d/pkg`, `builds/rapier3d/pkg`, etc. To build the `-compat` variant of the
+packages, run `npm run build` in the `rapier-compat` directory. Note that this will only work if you already ran
+`prepare_all_projects.sh`. The compat packages are then generated in, e.g., `rapier-compat/builds/3d/pkg`.
+
+## Feature selection
+
+Multiple NPM packages exist for Rapier, depending on your needs:
+- [`@dimforge/rapier2d`](https://www.npmjs.com/package/@dimforge/rapier2d) or
+ [`@dimforge/rapier3d`](https://www.npmjs.com/package/@dimforge/rapier3d):
+ The main build of the Rapier physics engine for 2D or 3D physics simulation. This should have wide browser
+ support while offering great performances. This does **not** guarantee cross-platform determinism of the physics
+ simulation (but it is still locally deterministic, on the same machine).
+- [`@dimforge/rapier2d-simd`](https://www.npmjs.com/package/@dimforge/rapier2d-simd) or
+ [`@dimforge/rapier3d-simd`](https://www.npmjs.com/package/@dimforge/rapier3d-simd):
+ A build with internal SIMD optimizations enabled. More limited browser support (requires support for [simd128](https://caniuse.com/?search=simd)).
+- [`@dimforge/rapier2d-deterministic`](https://www.npmjs.com/package/@dimforge/rapier2d-deterministic) or
+ [`@dimforge/rapier3d-deterministic`](https://www.npmjs.com/package/@dimforge/rapier3d-deterministic):
+ A less optimized build but with a guarantee of a cross-platform deterministic execution of the physics simulation.
+
+## Bundler support
+
+Some bundlers will struggle with the `.wasm` file package into the builds above. Alternative `-compat` versions exist
+which embed the `.wasm` file into the `.js` sources encoded with base64. This results in a bigger package size, but
+much wider bundler support.
+
+Just append `-compat` to the build you are interested in:
+[`rapier2d-compat`](https://www.npmjs.com/package/@dimforge/rapier2d-compat),
+[`rapier2d-simd-compat`](https://www.npmjs.com/package/@dimforge/rapier2d-simd-compat),
+[`rapier2d-deterministic-compat`](https://www.npmjs.com/package/@dimforge/rapier2d-deterministic-compat),
+[`rapier3d-compat`](https://www.npmjs.com/package/@dimforge/rapier3d-compat),
+[`rapier3d-simd-compat`](https://www.npmjs.com/package/@dimforge/rapier3d-simd-compat),
+[`rapier3d-deterministic-compat`](https://www.npmjs.com/package/@dimforge/rapier3d-deterministic-compat).
+
+## Nightly builds
+
+Each time a new Pull Request is merged to the `main` branch of the [`rapier.js` repository](https://github.com/dimforge/rapier.js),
+an automatic _canary_ build is triggered. Builds published to npmjs under the _canary_ tag does not come with any
+stability guarantee and does not follow semver versioning. But it can be a useful solution to try out the latest
+features until a proper release is cut.
\ No newline at end of file
diff --git a/typescript/builds/prepare_builds/Cargo.toml b/typescript/builds/prepare_builds/Cargo.toml
new file mode 100644
index 000000000..905de28fe
--- /dev/null
+++ b/typescript/builds/prepare_builds/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "prepare_builds"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+clap = { version = "4.5" }
+clap_derive = { version = "4.5" }
+tera = "1.20"
diff --git a/typescript/builds/prepare_builds/README.md b/typescript/builds/prepare_builds/README.md
new file mode 100644
index 000000000..4d05a2faa
--- /dev/null
+++ b/typescript/builds/prepare_builds/README.md
@@ -0,0 +1,17 @@
+# Prepare builds
+
+This project helps with making specific package: it takes a few parameter to create a (1) folder ready to compile.
+
+It uses clap so you can pass `-h` to get more info about its parameters.
+
+## usage
+
+At workspace root: `cargo run -p prepare_builds -- -d dim2 -f simd`.
+
+Or use provided scripts: `./builds/prepare_builds/prepare_all_projects.sh && ./builds/prepare_builds/build_all_projects.sh`
+
+## Technical considerations
+
+Askama/rinja was not chosen because compiled templates make it difficult to iterate on a folder and parse all templates.
+
+This folder is in `builds/` only for the workspace member glob to not complain if `builds/` is inexistent or empty.
diff --git a/typescript/builds/prepare_builds/build_all_projects.sh b/typescript/builds/prepare_builds/build_all_projects.sh
new file mode 100755
index 000000000..0f799a028
--- /dev/null
+++ b/typescript/builds/prepare_builds/build_all_projects.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+for entry in builds/*
+do
+ if [[ "$(basename "$entry")" == $(basename $(dirname "${BASH_SOURCE[0]}")) ]]; then
+ echo "skipping directory: $entry"
+ continue;
+ fi
+ (
+ cd $entry
+ echo "building $entry"
+ # FIXME: ideally we'd use `npm ci`
+ # but we'd need to have generated the `package-lock` beforehand and committed them in the repository.
+ # I'm not sure yet how to store those `package-lock`s yet though.
+ # They should probably be similar to all packages, but I'm not sure.
+ npm i;
+ npm run build;
+ )
+done
diff --git a/typescript/builds/prepare_builds/prepare_all_projects.sh b/typescript/builds/prepare_builds/prepare_all_projects.sh
new file mode 100755
index 000000000..bed9c147d
--- /dev/null
+++ b/typescript/builds/prepare_builds/prepare_all_projects.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+features=(non-deterministic deterministic simd)
+dims=(dim2 dim3)
+
+for feature in ${features[@]}; do
+ for dim in ${dims[@]}; do
+ echo "preparing dimension $dim with feature $feature"
+ cargo run -p prepare_builds -- -d ${dim} -f ${feature}
+ done
+done
diff --git a/typescript/builds/prepare_builds/src/main.rs b/typescript/builds/prepare_builds/src/main.rs
new file mode 100644
index 000000000..56675e8e1
--- /dev/null
+++ b/typescript/builds/prepare_builds/src/main.rs
@@ -0,0 +1,182 @@
+use std::{
+ error::Error,
+ fs::{self, File},
+ io::Write,
+ path::{Path, PathBuf},
+};
+
+use clap::Parser;
+use clap_derive::{Parser, ValueEnum};
+use tera::{Context, Tera};
+
+/// Simple program to greet a person
+#[derive(Parser, Debug)]
+#[command(version, about, long_about = None)]
+pub struct Args {
+ /// Dimension to use
+ #[arg(short, long)]
+ dim: Dimension,
+
+ /// Features to enable
+ #[arg(short, long)]
+ feature_set: FeatureSet,
+}
+
+#[derive(ValueEnum, Debug, Clone, Copy)]
+pub enum Dimension {
+ Dim2,
+ Dim3,
+}
+
+#[derive(ValueEnum, Default, Debug, Clone, Copy)]
+pub enum FeatureSet {
+ #[default]
+ NonDeterministic,
+ Deterministic,
+ Simd,
+}
+
+/// Values to use when creating the new build folder.
+pub struct BuildValues {
+ /// Only the number of dimensions, as sometimes it will be prefixed by "dim" and sometimes post-fixed by "d".
+ pub dim: String,
+ /// real name of the additional features to enable in the project
+ pub feature_set: Vec,
+ pub target_dir: PathBuf,
+ pub template_dir: PathBuf,
+ pub additional_rust_flags: String,
+ pub additional_wasm_opt_flags: Vec,
+ pub js_package_name: String,
+}
+
+impl BuildValues {
+ pub fn new(args: Args) -> Self {
+ let dim = match args.dim {
+ Dimension::Dim2 => "2",
+ Dimension::Dim3 => "3",
+ };
+ let feature_set = match args.feature_set {
+ FeatureSet::NonDeterministic => vec![],
+ FeatureSet::Deterministic => vec!["enhanced-determinism"],
+ FeatureSet::Simd => vec!["simd-stable"],
+ };
+ let js_package_name = match args.feature_set {
+ FeatureSet::NonDeterministic => format!("rapier{dim}d"),
+ FeatureSet::Deterministic => format!("rapier{dim}d-deterministic"),
+ FeatureSet::Simd => format!("rapier{dim}d-simd"),
+ };
+
+ let root: PathBuf = env!("CARGO_MANIFEST_DIR").into();
+
+ Self {
+ dim: dim.to_string(),
+ feature_set: feature_set.iter().map(|f| f.to_string()).collect(),
+ template_dir: root.join("templates/").clone(),
+ target_dir: root.parent().unwrap().join(&js_package_name).into(),
+ additional_rust_flags: match args.feature_set {
+ FeatureSet::Simd => "RUSTFLAGS='-C target-feature=+simd128'".to_string(),
+ _ => "".to_string(),
+ },
+ additional_wasm_opt_flags: match args.feature_set {
+ FeatureSet::Simd => vec!["--enable-simd".to_string()],
+ _ => vec![],
+ },
+ js_package_name,
+ }
+ }
+}
+
+fn main() {
+ let args = Args::parse();
+ dbg!(&args);
+
+ let build_values = BuildValues::new(args);
+ copy_top_level_files_in_directory(&build_values.template_dir, &build_values.target_dir)
+ .expect("Failed to copy directory");
+ process_templates(&build_values).expect("Failed to process templates");
+}
+
+fn copy_top_level_files_in_directory(
+ src: impl AsRef,
+ dest: impl AsRef,
+) -> std::io::Result<()> {
+ let src = src.as_ref();
+ let dest = Path::new(&dest);
+ if dest.exists() {
+ fs::remove_dir_all(&dest)?;
+ }
+ fs::create_dir_all(&dest)?;
+
+ for entry in fs::read_dir(src)? {
+ let entry = entry?;
+ let path = entry.path();
+ let dest_path = dest.join(path.file_name().unwrap());
+
+ if !path.is_dir() {
+ fs::copy(&path, &dest_path)?;
+ }
+ }
+ Ok(())
+}
+
+/// Process all tera templates in the target directory:
+/// - Remove the extension
+/// - Render the templates to
+///
+fn process_templates(build_values: &BuildValues) -> std::io::Result<()> {
+ let target_dir = build_values.target_dir.clone();
+
+ let mut context = Context::new();
+ context.insert("dimension", &build_values.dim);
+ context.insert("additional_features", &build_values.feature_set);
+ context.insert("additional_rust_flags", &build_values.additional_rust_flags);
+ context.insert(
+ "additional_wasm_opt_flags",
+ &build_values.additional_wasm_opt_flags,
+ );
+ context.insert("js_package_name", &build_values.js_package_name);
+
+ let tera = match Tera::new(target_dir.join("**/*.tera").to_str().unwrap()) {
+ Ok(t) => t,
+ Err(e) => {
+ eprintln!("Parsing error(s): {}", e);
+ ::std::process::exit(1);
+ }
+ };
+ dbg!(tera.templates.keys(), &context);
+
+ for entry in fs::read_dir(target_dir)? {
+ let entry = entry?;
+ let path = entry.path();
+ // For tera templates, remove extension.
+ if path.extension() == Some(std::ffi::OsStr::new("tera")) {
+ let mut i = path.iter();
+
+ // Get path from target directory
+ for _ in i
+ .by_ref()
+ .take_while(|c| *c != build_values.target_dir.file_name().unwrap())
+ {}
+ let path_template = i.as_path();
+ match tera.render(path_template.to_str().unwrap(), &context) {
+ Ok(s) => {
+ let old_path = path.clone();
+ let new_path = path.with_extension("");
+ let mut file = File::create(path.join(new_path))?;
+ file.write_all(s.as_bytes())?;
+ std::fs::remove_file(old_path)?;
+ }
+ Err(e) => {
+ eprintln!("Error: {}", e);
+ let mut cause = e.source();
+ while let Some(e) = cause {
+ eprintln!("Reason: {}", e);
+ cause = e.source();
+ }
+ }
+ };
+ }
+ }
+
+ Ok(())
+}
diff --git a/typescript/builds/prepare_builds/templates/Cargo.toml.tera b/typescript/builds/prepare_builds/templates/Cargo.toml.tera
new file mode 100644
index 000000000..da4702979
--- /dev/null
+++ b/typescript/builds/prepare_builds/templates/Cargo.toml.tera
@@ -0,0 +1,66 @@
+[package]
+name = "dimforge_{{ js_package_name }}" # Can't be named rapier{{ dimension }}d which conflicts with the dependency.
+version = "0.19.3"
+authors = ["Sébastien Crozet "]
+description = "{{ dimension }}-dimensional physics engine in Rust - official JS bindings."
+documentation = "https://rapier.rs/rustdoc/rapier{{ dimension }}d/index.html"
+homepage = "https://rapier.rs"
+repository = "https://github.com/dimforge/rapier.js"
+readme = "README.md"
+keywords = ["physics", "dynamics", "rigid", "real-time", "joints"]
+license = "Apache-2.0"
+edition = "2018"
+
+[features]
+default = ["dim{{ dimension }}"]
+dim{{ dimension }} = []
+
+[lib]
+name = "rapier_wasm{{ dimension }}d"
+path = "../../src/lib.rs"
+crate-type = ["cdylib", "rlib"]
+required-features = ["dim{{ dimension }}"]
+
+[lints]
+rust.unexpected_cfgs = { level = "warn", check-cfg = [
+ 'cfg(feature, values("dim{% if dimension == "2" %}3{% else %}2{% endif %}"))',
+] }
+
+[dependencies]
+# `rapier{2,3}d` is patched to the in-repo crate (see the workspace
+# `[patch.crates-io]` in ../../Cargo.toml); this version requirement must stay
+# semver-compatible with that crate's version for the patch to take effect.
+rapier{{ dimension }}d = { version = "0.34", features = [
+ "serde-serialize",
+ "debug-render",
+ "profiler",
+ {%- for feature in additional_features %}
+ "{{ feature }}",
+ {%- endfor %}
+] }
+# The explicit dependency to parry only needed to pin the version; it must match
+# the version (and math-backend feature set) the in-repo rapier crate depends on.
+parry{{ dimension }}d = { version = "0.29", default-features = false, features = [
+ "required-features",
+] }
+ref-cast = "1"
+wasm-bindgen = "0.2.109"
+js-sys = "0.3"
+nalgebra = "0.35"
+serde = { version = "1", features = ["derive", "rc"] }
+bincode = "1"
+palette = "0.7"
+
+[package.metadata.wasm-pack.profile.release]
+# add -g to keep debug symbols
+wasm-opt = [
+ '-O4',
+ '--dce',
+ # The two options below are needed because of: https://github.com/rustwasm/wasm-pack/issues/1501
+ '--enable-bulk-memory',
+ '--enable-nontrapping-float-to-int',
+ {%- for flag in additional_wasm_opt_flags %}
+ '{{ flag }}',
+ {%- endfor %}
+]
+#wasm-opt = ['-g']
diff --git a/typescript/builds/prepare_builds/templates/LICENSE b/typescript/builds/prepare_builds/templates/LICENSE
new file mode 100644
index 000000000..e579674df
--- /dev/null
+++ b/typescript/builds/prepare_builds/templates/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2020 Dimforge EURL
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/typescript/builds/prepare_builds/templates/README.md.tera b/typescript/builds/prepare_builds/templates/README.md.tera
new file mode 100644
index 000000000..3455eab2b
--- /dev/null
+++ b/typescript/builds/prepare_builds/templates/README.md.tera
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Website | Documentation
+
+
+
+---
+
+
+{{ dimension }}D physics engine
+for the JavaScript programming language (official bindings).
+
+
+---
+
+## Feature selection
+
+Multiple NPM packages exist for Rapier, depending on your needs:
+- [`@dimforge/rapier2d`](https://www.npmjs.com/package/@dimforge/rapier2d) or
+ [`@dimforge/rapier3d`](https://www.npmjs.com/package/@dimforge/rapier3d):
+ The main build of the Rapier physics engine for 2D or 3D physics simulation. This should have wide browser
+ support while offering great performances. This does **not** guarantee cross-platform determinism of the physics
+ simulation (but it is still locally deterministic, on the same machine).
+- [`@dimforge/rapier2d-simd`](https://www.npmjs.com/package/@dimforge/rapier2d-simd) or
+ [`@dimforge/rapier3d-simd`](https://www.npmjs.com/package/@dimforge/rapier3d-simd):
+ A build with internal SIMD optimizations enabled. More limited browser support (requires support for [simd128](https://caniuse.com/?search=simd)).
+- [`@dimforge/rapier2d-deterministic`](https://www.npmjs.com/package/@dimforge/rapier2d-deterministic) or
+ [`@dimforge/rapier3d-deterministic`](https://www.npmjs.com/package/@dimforge/rapier3d-deterministic):
+ A less optimized build but with a guarantee of a cross-platform deterministic execution of the physics simulation.
+
+## Bundler support
+
+Some bundlers will struggle with the `.wasm` file package into the builds above. Alternative `-compat` versions exist
+which embed the `.wasm` file into the `.js` sources encoded with base64. This results in a bigger package size, but
+much wider bundler support.
+
+Just append `-compat` to the build you are interested in:
+[`rapier2d-compat`](https://www.npmjs.com/package/@dimforge/rapier2d-compat),
+[`rapier2d-simd-compat`](https://www.npmjs.com/package/@dimforge/rapier2d-simd-compat),
+[`rapier2d-deterministic-compat`](https://www.npmjs.com/package/@dimforge/rapier2d-deterministic-compat),
+[`rapier3d-compat`](https://www.npmjs.com/package/@dimforge/rapier3d-compat),
+[`rapier3d-simd-compat`](https://www.npmjs.com/package/@dimforge/rapier3d-simd-compat),
+[`rapier3d-deterministic-compat`](https://www.npmjs.com/package/@dimforge/rapier3d-deterministic-compat).
+
+## Nightly builds
+
+Each time a new Pull Request is merged to the `main` branch of the [`rapier.js` repository](https://github.com/dimforge/rapier.js),
+an automatic _canary_ build is triggered. Builds published to npmjs under the _canary_ tag does not come with any
+stability guarantee and does not follow semver versioning. But it can be a useful solution to try out the latest
+features until a proper release is cut.
\ No newline at end of file
diff --git a/typescript/builds/prepare_builds/templates/build_rust.sh.tera b/typescript/builds/prepare_builds/templates/build_rust.sh.tera
new file mode 100755
index 000000000..6fd6ae824
--- /dev/null
+++ b/typescript/builds/prepare_builds/templates/build_rust.sh.tera
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+# Cleaning rust because changing rust flags may lead to different build results.
+cargo clean
+
+{{ additional_rust_flags }} npx wasm-pack build
+sed -i.bak 's#dimforge_rapier#@dimforge/rapier#g' pkg/package.json
+sed -i.bak 's/"rapier_wasm{{ dimension }}d_bg.wasm"/"*"/g' pkg/package.json
+(
+ cd pkg
+ npm pkg delete sideEffects
+ npm pkg set 'sideEffects[0]'="./*.js"
+)
+rm pkg/*.bak
+rm pkg/.gitignore
diff --git a/typescript/builds/prepare_builds/templates/build_typescript.sh.tera b/typescript/builds/prepare_builds/templates/build_typescript.sh.tera
new file mode 100755
index 000000000..8fcce98bc
--- /dev/null
+++ b/typescript/builds/prepare_builds/templates/build_typescript.sh.tera
@@ -0,0 +1,13 @@
+#! /bin/sh
+
+mkdir -p ./pkg/src
+cp -r ../../src.ts/* pkg/src/.
+rm -f ./pkg/raw.ts
+echo 'export * from "./rapier_wasm{{ dimension }}d"' > pkg/src/raw.ts
+# See https://serverfault.com/a/137848
+find pkg/ -type f -print0 | LC_ALL=C xargs -0 sed -i.bak '\:#if DIM{% if dimension == "2" %}3{% else %}2{% endif %}:,\:#endif:d'
+npx tsc
+# NOTE: we keep the typescripts files into the NPM package for source mapping: see #3
+sed -i.bak 's/"module": "rapier_wasm{{ dimension }}d.js"/"module": "rapier.js"/g' pkg/package.json
+sed -i.bak 's/"types": "rapier_wasm{{ dimension }}d.d.ts"/"types": "rapier.d.ts"/g' pkg/package.json
+find pkg/ -type f -name '*.bak' | xargs rm
diff --git a/typescript/builds/prepare_builds/templates/package.json.tera b/typescript/builds/prepare_builds/templates/package.json.tera
new file mode 100644
index 000000000..d596c1960
--- /dev/null
+++ b/typescript/builds/prepare_builds/templates/package.json.tera
@@ -0,0 +1,26 @@
+{
+ "name": "@dimforge/{{ js_package_name }}",
+ "description": "",
+ "private": true,
+ "exports": "./pkg",
+ "types": "./pkg/rapier.d.ts",
+ "scripts": {
+ "build": "npm run clean && npm run build:wasm && npm run build:ts && npm run build:doc",
+ "build:doc": "typedoc --tsconfig tsconfig_typedoc.json",
+ "build:wasm": "sh ./build_rust.sh",
+ "build:ts": "sh ./build_typescript.sh",
+ "clean": "rimraf pkg"
+ },
+ "//": "Better keep rimraf version in sync with wasm-pack, see https://github.com/rustwasm/wasm-pack/issues/1444",
+ "devDependencies": {
+ "rimraf": "^3.0.2",
+ "typedoc": "^0.25.13",
+ "typescript": "~5.4.5"
+ },
+ "dependencies": {
+ "wasm-pack": "^0.12.1"
+ },
+ "sideEffects": [
+ "./*.js"
+ ]
+}
\ No newline at end of file
diff --git a/typescript/builds/prepare_builds/templates/tsconfig.json b/typescript/builds/prepare_builds/templates/tsconfig.json
new file mode 100644
index 000000000..1614ac78e
--- /dev/null
+++ b/typescript/builds/prepare_builds/templates/tsconfig.json
@@ -0,0 +1,13 @@
+{
+ "compilerOptions": {
+ "outDir": "./pkg",
+ "module": "ES6",
+ "target": "es6",
+ "lib": ["es6", "ESNext.Disposable"],
+ "moduleResolution": "node",
+ "sourceMap": true,
+ "declaration": true,
+ "rootDirs": ["./pkg", "./pkg/src"]
+ },
+ "files": ["./pkg/src/rapier.ts"]
+}
diff --git a/typescript/builds/prepare_builds/templates/tsconfig_typedoc.json b/typescript/builds/prepare_builds/templates/tsconfig_typedoc.json
new file mode 100644
index 000000000..f6958d5cf
--- /dev/null
+++ b/typescript/builds/prepare_builds/templates/tsconfig_typedoc.json
@@ -0,0 +1,10 @@
+{
+ "compilerOptions": {
+ "outDir": "./pkg",
+ "moduleResolution": "node",
+ "sourceMap": true,
+ "declaration": true,
+ "lib": ["es6", "ESNext.Disposable"]
+ },
+ "files": ["./pkg/rapier.d.ts"]
+}
diff --git a/typescript/builds/prepare_builds/templates/typedoc.json.tera b/typescript/builds/prepare_builds/templates/typedoc.json.tera
new file mode 100644
index 000000000..d96bb7a64
--- /dev/null
+++ b/typescript/builds/prepare_builds/templates/typedoc.json.tera
@@ -0,0 +1,42 @@
+{
+ "$schema": "https://typedoc.org/schema.json",
+ "entryPoints": [
+ "./pkg/rapier.d.ts"
+ ],
+ "out": "./docs",
+ "readme": "none",
+ "excludeExternals": true,
+ "excludeNotDocumented": false,
+ "intentionallyNotExported": [
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawBroadPhase",
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawCCDSolver",
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawColliderSet",
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawEventQueue",
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawImpulseJointSet",
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawMultibodyJointSet",
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawIntegrationParameters",
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawIslandManager",
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawNarrowPhase",
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawPhysicsPipeline",
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawRigidBodySet",
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawSerializationPipeline",
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawContactManifold",
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawShape",
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawGenericJoint",
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawJointAxis",
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawRotation",
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawVector",
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawPointColliderProjection",
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawPointProjection",
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawRayColliderIntersection",
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawRayColliderHit",
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawRayIntersection",
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawColliderShapeCastHit",
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawShapeContact",
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawShapeCastHit",
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawQueryPipeline",
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawDeserializedWorld",
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawDebugRenderPipeline",
+ "pkg/rapier_wasm{{ dimension }}d.d.ts:RawContactForceEvent"
+ ]
+}
\ No newline at end of file
diff --git a/typescript/package-lock.json b/typescript/package-lock.json
new file mode 100644
index 000000000..f82e399b4
--- /dev/null
+++ b/typescript/package-lock.json
@@ -0,0 +1,506 @@
+{
+ "name": "rapier.js",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "devDependencies": {
+ "prettier": "2.7.1",
+ "typedoc": "0.23.19",
+ "typescript": "4.8.4",
+ "wasm-opt": "1.4.0",
+ "wasm-pack": "0.12.1"
+ }
+ },
+ "node_modules/axios": {
+ "version": "0.26.1",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz",
+ "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "follow-redirects": "^1.14.8"
+ }
+ },
+ "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,
+ "license": "MIT"
+ },
+ "node_modules/binary-install": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/binary-install/-/binary-install-1.1.0.tgz",
+ "integrity": "sha512-rkwNGW+3aQVSZoD0/o3mfPN6Yxh3Id0R/xzTVBVVpGNlVz8EGwusksxRlbk/A5iKTZt9zkMn3qIqmAt3vpfbzg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "axios": "^0.26.1",
+ "rimraf": "^3.0.2",
+ "tar": "^6.1.11"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "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,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/chownr": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+ "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "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/follow-redirects": {
+ "version": "1.15.9",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
+ "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/fs-minipass": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
+ "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/fs-minipass/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=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,
+ "license": "ISC"
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Glob versions prior to v9 are no longer supported",
+ "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/glob/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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/glob/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "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": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/jsonc-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz",
+ "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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,
+ "license": "MIT"
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "marked": "bin/marked.js"
+ },
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
+ "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/minipass": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
+ "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minizlib": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
+ "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "minipass": "^3.0.0",
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/minizlib/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/node-fetch": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "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,
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "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,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
+ "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "prettier": "bin-prettier.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "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/shiki": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.11.1.tgz",
+ "integrity": "sha512-EugY9VASFuDqOexOgXR18ZV+TbFrQHeCpEYaXamO+SZlsnT/2LxuLBX25GGtIrwaEVFXUAbUQ601SWE2rMwWHA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jsonc-parser": "^3.0.0",
+ "vscode-oniguruma": "^1.6.1",
+ "vscode-textmate": "^6.0.0"
+ }
+ },
+ "node_modules/tar": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
+ "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.0.0",
+ "minipass": "^5.0.0",
+ "minizlib": "^2.1.1",
+ "mkdirp": "^1.0.3",
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/typedoc": {
+ "version": "0.23.19",
+ "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.19.tgz",
+ "integrity": "sha512-70jPL0GQnSJtgQqI7ifOWxpTXrB3sxc4SWPPRn3K0wdx3txI6ZIT/ZYMF39dNg2Gjmql45cO+cAKXJp0TpqOVA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "lunr": "^2.3.9",
+ "marked": "^4.0.19",
+ "minimatch": "^5.1.0",
+ "shiki": "^0.11.1"
+ },
+ "bin": {
+ "typedoc": "bin/typedoc"
+ },
+ "engines": {
+ "node": ">= 14.14"
+ },
+ "peerDependencies": {
+ "typescript": "4.6.x || 4.7.x || 4.8.x"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "4.8.4",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz",
+ "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ },
+ "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,
+ "license": "MIT"
+ },
+ "node_modules/vscode-textmate": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-6.0.0.tgz",
+ "integrity": "sha512-gu73tuZfJgu+mvCSy4UZwd2JXykjK9zAZsfmDeut5dx/1a7FeTk0XwJsSuqQn+cuMCGVbIBfl+s53X4T19DnzQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/wasm-opt": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/wasm-opt/-/wasm-opt-1.4.0.tgz",
+ "integrity": "sha512-wIsxxp0/FOSphokH4VOONy1zPkVREQfALN+/JTvJPK8gFSKbsmrcfECu2hT7OowqPfb4WEMSMceHgNL0ipFRyw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "dependencies": {
+ "node-fetch": "^2.6.9",
+ "tar": "^6.1.13"
+ },
+ "bin": {
+ "wasm-opt": "bin/wasm-opt.js"
+ }
+ },
+ "node_modules/wasm-pack": {
+ "version": "0.12.1",
+ "resolved": "https://registry.npmjs.org/wasm-pack/-/wasm-pack-0.12.1.tgz",
+ "integrity": "sha512-dIyKWUumPFsGohdndZjDXRFaokUT/kQS+SavbbiXVAvA/eN4riX5QNdB6AhXQx37zNxluxQkuixZUgJ8adKjOg==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT OR Apache-2.0",
+ "dependencies": {
+ "binary-install": "^1.0.1"
+ },
+ "bin": {
+ "wasm-pack": "run.js"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "BSD-2-Clause"
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
+ "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/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true,
+ "license": "ISC"
+ }
+ }
+}
diff --git a/typescript/package.json b/typescript/package.json
new file mode 100644
index 000000000..ce0eec04c
--- /dev/null
+++ b/typescript/package.json
@@ -0,0 +1,12 @@
+{
+ "scripts": {
+ "fmt": "prettier ."
+ },
+ "devDependencies": {
+ "prettier": "2.7.1",
+ "typedoc": "0.23.19",
+ "typescript": "4.8.4",
+ "wasm-opt": "1.4.0",
+ "wasm-pack": "0.12.1"
+ }
+}
diff --git a/typescript/publish_all_canary.sh b/typescript/publish_all_canary.sh
new file mode 100755
index 000000000..211554299
--- /dev/null
+++ b/typescript/publish_all_canary.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+for entry in builds/*/pkg
+do
+ (
+ echo "Publishing $entry"
+ cd $entry; npm version 0.0.0-$(git rev-parse --short HEAD)-$(date '+%Y%m%d') --git-tag-version false;
+ npm publish --tag canary --access public;
+ )
+done;
+
+for entry in rapier-compat/builds/*/pkg
+do
+ (
+ echo "Publishing $entry"
+ cd $entry; npm version 0.0.0-$(git rev-parse --short HEAD)-$(date '+%Y%m%d') --git-tag-version false;
+ npm publish --tag canary --access public;
+ )
+done;
\ No newline at end of file
diff --git a/typescript/publish_all_prod.sh b/typescript/publish_all_prod.sh
new file mode 100755
index 000000000..f04915cb5
--- /dev/null
+++ b/typescript/publish_all_prod.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+for entry in builds/*/pkg
+do
+ (
+ echo "Publishing $entry"
+ cd $entry;
+ npm publish --access public;
+ )
+done;
+
+for entry in rapier-compat/builds/*/pkg
+do
+ (
+ echo "Publishing $entry"
+ cd $entry;
+ npm publish --access public;
+ )
+done;
\ No newline at end of file
diff --git a/typescript/rapier-compat/README.md b/typescript/rapier-compat/README.md
new file mode 100644
index 000000000..5d440ec26
--- /dev/null
+++ b/typescript/rapier-compat/README.md
@@ -0,0 +1,16 @@
+# tsconfig json files
+
+- tsconfig.common.json - shared TypeScript options
+- tsconfig.pkg2d.json - config for compiling rapier2d-compat
+- tsconfig.pkg3d.json - config for compiling rapier3d-compat
+- tconfig.json - for IDE (VSCode) and unit tests. Includes Jest types.
+
+## Generation steps
+
+Check `./package.json scripts`, which are used by CI.
+
+Summary:
+
+- build rust wasm projects into their dedicated folder in `./builds/`
+- copy common javascript and generate dimension specific javascript into a common `./pkg` folder
+- copy that `pkg` folder in each folder from `./builds`
diff --git a/typescript/rapier-compat/build-rust.sh b/typescript/rapier-compat/build-rust.sh
new file mode 100755
index 000000000..2acd18f88
--- /dev/null
+++ b/typescript/rapier-compat/build-rust.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+
+
+help()
+{
+ printf "Usage: %s: [-d 2|3] [-f deterministim|non-deterministic|simd]\n" $0
+}
+
+while getopts :d:f: name
+do
+ case $name in
+ d)
+ dimension="$OPTARG";;
+ f)
+ feature="$OPTARG";;
+ ?) help ; exit 1;;
+ esac
+done
+
+if [[ -z "$dimension" ]]; then
+ help; exit 2;
+fi
+if [[ -z "$feature" ]]; then
+ help; exit 3;
+fi
+
+if [[ $feature == "non-deterministic" ]]; then
+ feature_postfix=""
+else
+ feature_postfix="-${feature}"
+fi
+
+rust_source_directory="../builds/rapier${dimension}d${feature_postfix}"
+
+if [ ! -d "$rust_source_directory" ]; then
+ echo "Directory $rust_source_directory does not exist";
+ echo "You may want to generate rust projects first.";
+ help
+ exit 4;
+fi
+
+# Working dir in wasm-pack is the project root so we need that "../../"
+
+if [[ $feature == "simd" ]]; then
+ export additional_rustflags='-C target-feature=+simd128'
+else
+ export additional_rustflags=''
+fi
+
+RUSTFLAGS="${additional_rustflags}" wasm-pack --verbose build --target web --out-dir "../../rapier-compat/builds/${dimension}d${feature_postfix}/wasm-build" "$rust_source_directory"
diff --git a/typescript/rapier-compat/fix_raw_file.sh b/typescript/rapier-compat/fix_raw_file.sh
new file mode 100644
index 000000000..66f8bfafc
--- /dev/null
+++ b/typescript/rapier-compat/fix_raw_file.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+for feature in \
+2d 2d-deterministic 2d-simd \
+3d 3d-deterministic 3d-simd
+do
+
+echo 'export * from "'"./rapier_wasm$feature"'"' > builds/${feature}/pkg/raw.d.ts
+echo 'export * from "'"./rapier_wasm$feature"'"' > builds/${feature}/pkg/raw.d.ts
+
+done;
\ No newline at end of file
diff --git a/typescript/rapier-compat/gen_src.sh b/typescript/rapier-compat/gen_src.sh
new file mode 100755
index 000000000..24ccc4418
--- /dev/null
+++ b/typescript/rapier-compat/gen_src.sh
@@ -0,0 +1,58 @@
+# Copy source and remove #if sections - similar to script in ../rapierXd
+set -e
+
+gen_js() {
+ DIM=$1
+ GENOUT="./gen${DIM}"
+
+ # Make output directories
+ mkdir -p ${GENOUT}
+
+ # Copy common sources
+ cp -r ../src.ts/* $GENOUT
+
+ # Copy compat mode override sources
+ rm -f "${GENOUT}/raw.ts" "${GENOUT}/init.ts"
+ cp -r ./src${DIM}/* $GENOUT
+}
+
+gen_js "2d"
+gen_js "3d"
+
+# See https://serverfault.com/a/137848
+find gen2d/ -type f -print0 | LC_ALL=C xargs -0 sed -i.bak '\:#if DIM3:,\:#endif:d'
+find gen3d/ -type f -print0 | LC_ALL=C xargs -0 sed -i.bak '\:#if DIM2:,\:#endif:d'
+
+# Clean up backup files.
+find gen2d/ -type f -name '*.bak' | xargs rm
+find gen3d/ -type f -name '*.bak' | xargs rm
+
+for features_set in \
+"2" "2 deterministic" "2 simd" \
+"3" "3 deterministic" "3 simd"
+do
+
+ set -- $features_set # Convert the "tuple" into the param args $1 $2...
+ dimension=$1
+ if [ -z "$2" ]; then
+ feature="${1}d";
+ else
+ feature="${1}d-${2}";
+ fi
+
+ mkdir -p ./builds/${feature}/pkg/
+
+ cp ./builds/${feature}/wasm-build/rapier_wasm* ./builds/${feature}/pkg/
+ cp -r ./gen${dimension}d ./builds/${feature}/
+
+ # copy tsconfig, as they contain paths
+ cp ./tsconfig.common.json ./tsconfig.json ./builds/${feature}/
+ cp ./tsconfig.pkg${dimension}d.json ./builds/${feature}/tsconfig.pkg.json
+
+ # "import.meta" causes Babel to choke, but the code path is never taken so just remove it.
+ sed -i.bak 's/import.meta.url/""/g' ./builds/${feature}/pkg/rapier_wasm${dimension}d.js
+
+ # Clean up backup files.
+ find ./builds/${feature}/pkg/ -type f -name '*.bak' | xargs rm
+
+done
diff --git a/typescript/rapier-compat/package-lock.json b/typescript/rapier-compat/package-lock.json
new file mode 100644
index 000000000..22b6f0231
--- /dev/null
+++ b/typescript/rapier-compat/package-lock.json
@@ -0,0 +1,10500 @@
+{
+ "name": "build-rapier",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "build-rapier",
+ "dependencies": {
+ "base64-js": "^1.5.1"
+ },
+ "devDependencies": {
+ "@rollup/plugin-commonjs": "^23.0.2",
+ "@rollup/plugin-node-resolve": "^15.0.1",
+ "@rollup/plugin-terser": "0.1.0",
+ "@rollup/plugin-typescript": "^9.0.2",
+ "@types/jest": "^29.2.1",
+ "jest": "^29.2.2",
+ "rimraf": "^3.0.2",
+ "rollup": "^3.2.5",
+ "rollup-plugin-base64": "^1.0.1",
+ "rollup-plugin-copy": "^3.4.0",
+ "rollup-plugin-filesize": "^9.1.2",
+ "ts-jest": "^29.0.3",
+ "tslib": "^2.4.1",
+ "typescript": "^4.8.4"
+ }
+ },
+ "node_modules/@ampproject/remapping": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
+ "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.1.0",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz",
+ "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/highlight": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.20.1",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.1.tgz",
+ "integrity": "sha512-EWZ4mE2diW3QALKvDMiXnbZpRvlj+nayZ112nK93SnhqOtpdsbVD4W+2tEoT3YNBAG9RBR0ISY758ZkOgsn6pQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.19.6",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.6.tgz",
+ "integrity": "sha512-D2Ue4KHpc6Ys2+AxpIx1BZ8+UegLLLE2p3KJEuJRKmokHOtl49jQ5ny1773KsGLZs8MQvBidAF6yWUJxRqtKtg==",
+ "dev": true,
+ "dependencies": {
+ "@ampproject/remapping": "^2.1.0",
+ "@babel/code-frame": "^7.18.6",
+ "@babel/generator": "^7.19.6",
+ "@babel/helper-compilation-targets": "^7.19.3",
+ "@babel/helper-module-transforms": "^7.19.6",
+ "@babel/helpers": "^7.19.4",
+ "@babel/parser": "^7.19.6",
+ "@babel/template": "^7.18.10",
+ "@babel/traverse": "^7.19.6",
+ "@babel/types": "^7.19.4",
+ "convert-source-map": "^1.7.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.1",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.20.1",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.1.tgz",
+ "integrity": "sha512-u1dMdBUmA7Z0rBB97xh8pIhviK7oItYOkjbsCxTWMknyvbQRBwX7/gn4JXurRdirWMFh+ZtYARqkA6ydogVZpg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.20.0",
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "jsesc": "^2.5.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
+ "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/set-array": "^1.0.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.20.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.0.tgz",
+ "integrity": "sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.20.0",
+ "@babel/helper-validator-option": "^7.18.6",
+ "browserslist": "^4.21.3",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-environment-visitor": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz",
+ "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-function-name": {
+ "version": "7.19.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz",
+ "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==",
+ "dev": true,
+ "dependencies": {
+ "@babel/template": "^7.18.10",
+ "@babel/types": "^7.19.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-hoist-variables": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz",
+ "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz",
+ "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.19.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.6.tgz",
+ "integrity": "sha512-fCmcfQo/KYr/VXXDIyd3CBGZ6AFhPFy1TfSEJ+PilGVlQT6jcbqtHAM4C1EciRqMza7/TpOUZliuSH+U6HAhJw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-module-imports": "^7.18.6",
+ "@babel/helper-simple-access": "^7.19.4",
+ "@babel/helper-split-export-declaration": "^7.18.6",
+ "@babel/helper-validator-identifier": "^7.19.1",
+ "@babel/template": "^7.18.10",
+ "@babel/traverse": "^7.19.6",
+ "@babel/types": "^7.19.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.19.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz",
+ "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-simple-access": {
+ "version": "7.19.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.19.4.tgz",
+ "integrity": "sha512-f9Xq6WqBFqaDfbCzn2w85hwklswz5qsKlh7f08w4Y9yhJHpnNC0QemtSkK5YyOY8kPGvyiwdzZksGUhnGdaUIg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.19.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-split-export-declaration": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz",
+ "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.19.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz",
+ "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.19.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz",
+ "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz",
+ "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.20.1",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.1.tgz",
+ "integrity": "sha512-J77mUVaDTUJFZ5BpP6mMn6OIl3rEWymk2ZxDBQJUG3P+PbmyMcF3bYWvz0ma69Af1oobDqT/iAsvzhB58xhQUg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/template": "^7.18.10",
+ "@babel/traverse": "^7.20.1",
+ "@babel/types": "^7.20.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
+ "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ },
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.20.1",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.1.tgz",
+ "integrity": "sha512-hp0AYxaZJhxULfM1zyp7Wgr+pSUKBcP3M+PHnSzWGdXOzg/kHWIgiUWARvubhUKGOEw3xqY4x+lyZ9ytBVcELw==",
+ "dev": true,
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-async-generators": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
+ "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-bigint": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz",
+ "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-class-properties": {
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
+ "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.12.13"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-import-meta": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
+ "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-json-strings": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+ "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-jsx": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz",
+ "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+ "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+ "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-numeric-separator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+ "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-catch-binding": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+ "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-chaining": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-top-level-await": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
+ "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-typescript": {
+ "version": "7.20.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz",
+ "integrity": "sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.19.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.17.8",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.8.tgz",
+ "integrity": "sha512-dQpEpK0O9o6lj6oPu0gRDbbnk+4LeHlNcBpspf6Olzt3GIX4P1lWF1gS+pHLDFlaJvbR6q7jCfQ08zA4QJBnmA==",
+ "dev": true,
+ "dependencies": {
+ "regenerator-runtime": "^0.13.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz",
+ "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.18.6",
+ "@babel/parser": "^7.18.10",
+ "@babel/types": "^7.18.10"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.20.1",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.1.tgz",
+ "integrity": "sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.18.6",
+ "@babel/generator": "^7.20.1",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-function-name": "^7.19.0",
+ "@babel/helper-hoist-variables": "^7.18.6",
+ "@babel/helper-split-export-declaration": "^7.18.6",
+ "@babel/parser": "^7.20.1",
+ "@babel/types": "^7.20.0",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.20.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.0.tgz",
+ "integrity": "sha512-Jlgt3H0TajCW164wkTOTzHkZb075tMQMULzrLUoUeKmO7eFL96GgDxf7/Axhc5CAuKE3KFyVW1p6ysKsi2oXAg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.19.4",
+ "@babel/helper-validator-identifier": "^7.19.1",
+ "to-fast-properties": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@bcoe/v8-coverage": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
+ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
+ "dev": true
+ },
+ "node_modules/@gar/promisify": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz",
+ "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==",
+ "dev": true
+ },
+ "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,
+ "dependencies": {
+ "camelcase": "^5.3.1",
+ "find-up": "^4.1.0",
+ "get-package-type": "^0.1.0",
+ "js-yaml": "^3.13.1",
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@jest/console": {
+ "version": "29.2.1",
+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.2.1.tgz",
+ "integrity": "sha512-MF8Adcw+WPLZGBiNxn76DOuczG3BhODTcMlDCA4+cFi41OkaY/lyI0XUUhi73F88Y+7IHoGmD80pN5CtxQUdSw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.2.1",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "jest-message-util": "^29.2.1",
+ "jest-util": "^29.2.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/core": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.2.2.tgz",
+ "integrity": "sha512-susVl8o2KYLcZhhkvSB+b7xX575CX3TmSvxfeDjpRko7KmT89rHkXj6XkDkNpSeFMBzIENw5qIchO9HC9Sem+A==",
+ "dev": true,
+ "dependencies": {
+ "@jest/console": "^29.2.1",
+ "@jest/reporters": "^29.2.2",
+ "@jest/test-result": "^29.2.1",
+ "@jest/transform": "^29.2.2",
+ "@jest/types": "^29.2.1",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "jest-changed-files": "^29.2.0",
+ "jest-config": "^29.2.2",
+ "jest-haste-map": "^29.2.1",
+ "jest-message-util": "^29.2.1",
+ "jest-regex-util": "^29.2.0",
+ "jest-resolve": "^29.2.2",
+ "jest-resolve-dependencies": "^29.2.2",
+ "jest-runner": "^29.2.2",
+ "jest-runtime": "^29.2.2",
+ "jest-snapshot": "^29.2.2",
+ "jest-util": "^29.2.1",
+ "jest-validate": "^29.2.2",
+ "jest-watcher": "^29.2.2",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.2.1",
+ "slash": "^3.0.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@jest/environment": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.2.2.tgz",
+ "integrity": "sha512-OWn+Vhu0I1yxuGBJEFFekMYc8aGBGrY4rt47SOh/IFaI+D7ZHCk7pKRiSoZ2/Ml7b0Ony3ydmEHRx/tEOC7H1A==",
+ "dev": true,
+ "dependencies": {
+ "@jest/fake-timers": "^29.2.2",
+ "@jest/types": "^29.2.1",
+ "@types/node": "*",
+ "jest-mock": "^29.2.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/expect": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.2.2.tgz",
+ "integrity": "sha512-zwblIZnrIVt8z/SiEeJ7Q9wKKuB+/GS4yZe9zw7gMqfGf4C5hBLGrVyxu1SzDbVSqyMSlprKl3WL1r80cBNkgg==",
+ "dev": true,
+ "dependencies": {
+ "expect": "^29.2.2",
+ "jest-snapshot": "^29.2.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/expect-utils": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.2.2.tgz",
+ "integrity": "sha512-vwnVmrVhTmGgQzyvcpze08br91OL61t9O0lJMDyb6Y/D8EKQ9V7rGUb/p7PDt0GPzK0zFYqXWFo4EO2legXmkg==",
+ "dev": true,
+ "dependencies": {
+ "jest-get-type": "^29.2.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/fake-timers": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.2.2.tgz",
+ "integrity": "sha512-nqaW3y2aSyZDl7zQ7t1XogsxeavNpH6kkdq+EpXncIDvAkjvFD7hmhcIs1nWloengEWUoWqkqSA6MSbf9w6DgA==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.2.1",
+ "@sinonjs/fake-timers": "^9.1.2",
+ "@types/node": "*",
+ "jest-message-util": "^29.2.1",
+ "jest-mock": "^29.2.2",
+ "jest-util": "^29.2.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/globals": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.2.2.tgz",
+ "integrity": "sha512-/nt+5YMh65kYcfBhj38B3Hm0Trk4IsuMXNDGKE/swp36yydBWfz3OXkLqkSvoAtPW8IJMSJDFCbTM2oj5SNprw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/environment": "^29.2.2",
+ "@jest/expect": "^29.2.2",
+ "@jest/types": "^29.2.1",
+ "jest-mock": "^29.2.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/reporters": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.2.2.tgz",
+ "integrity": "sha512-AzjL2rl2zJC0njIzcooBvjA4sJjvdoq98sDuuNs4aNugtLPSQ+91nysGKRF0uY1to5k0MdGMdOBggUsPqvBcpA==",
+ "dev": true,
+ "dependencies": {
+ "@bcoe/v8-coverage": "^0.2.3",
+ "@jest/console": "^29.2.1",
+ "@jest/test-result": "^29.2.1",
+ "@jest/transform": "^29.2.2",
+ "@jest/types": "^29.2.1",
+ "@jridgewell/trace-mapping": "^0.3.15",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "exit": "^0.1.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "istanbul-lib-coverage": "^3.0.0",
+ "istanbul-lib-instrument": "^5.1.0",
+ "istanbul-lib-report": "^3.0.0",
+ "istanbul-lib-source-maps": "^4.0.0",
+ "istanbul-reports": "^3.1.3",
+ "jest-message-util": "^29.2.1",
+ "jest-util": "^29.2.1",
+ "jest-worker": "^29.2.1",
+ "slash": "^3.0.0",
+ "string-length": "^4.0.1",
+ "strip-ansi": "^6.0.0",
+ "v8-to-istanbul": "^9.0.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@jest/schemas": {
+ "version": "29.0.0",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.0.0.tgz",
+ "integrity": "sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA==",
+ "dev": true,
+ "dependencies": {
+ "@sinclair/typebox": "^0.24.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/source-map": {
+ "version": "29.2.0",
+ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.2.0.tgz",
+ "integrity": "sha512-1NX9/7zzI0nqa6+kgpSdKPK+WU1p+SJk3TloWZf5MzPbxri9UEeXX5bWZAPCzbQcyuAzubcdUHA7hcNznmRqWQ==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.15",
+ "callsites": "^3.0.0",
+ "graceful-fs": "^4.2.9"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/test-result": {
+ "version": "29.2.1",
+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.2.1.tgz",
+ "integrity": "sha512-lS4+H+VkhbX6z64tZP7PAUwPqhwj3kbuEHcaLuaBuB+riyaX7oa1txe0tXgrFj5hRWvZKvqO7LZDlNWeJ7VTPA==",
+ "dev": true,
+ "dependencies": {
+ "@jest/console": "^29.2.1",
+ "@jest/types": "^29.2.1",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "collect-v8-coverage": "^1.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/test-sequencer": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.2.2.tgz",
+ "integrity": "sha512-Cuc1znc1pl4v9REgmmLf0jBd3Y65UXJpioGYtMr/JNpQEIGEzkmHhy6W6DLbSsXeUA13TDzymPv0ZGZ9jH3eIw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/test-result": "^29.2.1",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.2.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/transform": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.2.2.tgz",
+ "integrity": "sha512-aPe6rrletyuEIt2axxgdtxljmzH8O/nrov4byy6pDw9S8inIrTV+2PnjyP/oFHMSynzGxJ2s6OHowBNMXp/Jzg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@jest/types": "^29.2.1",
+ "@jridgewell/trace-mapping": "^0.3.15",
+ "babel-plugin-istanbul": "^6.1.1",
+ "chalk": "^4.0.0",
+ "convert-source-map": "^1.4.0",
+ "fast-json-stable-stringify": "^2.1.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.2.1",
+ "jest-regex-util": "^29.2.0",
+ "jest-util": "^29.2.1",
+ "micromatch": "^4.0.4",
+ "pirates": "^4.0.4",
+ "slash": "^3.0.0",
+ "write-file-atomic": "^4.0.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/types": {
+ "version": "29.2.1",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.2.1.tgz",
+ "integrity": "sha512-O/QNDQODLnINEPAI0cl9U6zUIDXEWXt6IC1o2N2QENuos7hlGUIthlKyV4p6ki3TvXFX071blj8HUhgLGquPjw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/schemas": "^29.0.0",
+ "@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": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
+ "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/set-array": "^1.0.0",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/source-map": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz",
+ "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.0",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ }
+ },
+ "node_modules/@jridgewell/source-map/node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
+ "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/set-array": "^1.0.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "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/@jridgewell/trace-mapping": {
+ "version": "0.3.17",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz",
+ "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/resolve-uri": "3.1.0",
+ "@jridgewell/sourcemap-codec": "1.4.14"
+ }
+ },
+ "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,
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@npmcli/fs": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz",
+ "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==",
+ "dev": true,
+ "dependencies": {
+ "@gar/promisify": "^1.0.1",
+ "semver": "^7.3.5"
+ }
+ },
+ "node_modules/@npmcli/fs/node_modules/semver": {
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+ "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@npmcli/git": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-2.1.0.tgz",
+ "integrity": "sha512-/hBFX/QG1b+N7PZBFs0bi+evgRZcK9nWBxQKZkGoXUT5hJSwl5c4d7y8/hm+NQZRPhQ67RzFaj5UM9YeyKoryw==",
+ "dev": true,
+ "dependencies": {
+ "@npmcli/promise-spawn": "^1.3.2",
+ "lru-cache": "^6.0.0",
+ "mkdirp": "^1.0.4",
+ "npm-pick-manifest": "^6.1.1",
+ "promise-inflight": "^1.0.1",
+ "promise-retry": "^2.0.1",
+ "semver": "^7.3.5",
+ "which": "^2.0.2"
+ }
+ },
+ "node_modules/@npmcli/git/node_modules/semver": {
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+ "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@npmcli/installed-package-contents": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-1.0.7.tgz",
+ "integrity": "sha512-9rufe0wnJusCQoLpV9ZPKIVP55itrM5BxOXs10DmdbRfgWtHy1LDyskbwRnBghuB0PrF7pNPOqREVtpz4HqzKw==",
+ "dev": true,
+ "dependencies": {
+ "npm-bundled": "^1.1.1",
+ "npm-normalize-package-bin": "^1.0.1"
+ },
+ "bin": {
+ "installed-package-contents": "index.js"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@npmcli/move-file": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz",
+ "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==",
+ "dev": true,
+ "dependencies": {
+ "mkdirp": "^1.0.4",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@npmcli/node-gyp": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-1.0.3.tgz",
+ "integrity": "sha512-fnkhw+fmX65kiLqk6E3BFLXNC26rUhK90zVwe2yncPliVT/Qos3xjhTLE59Df8KnPlcwIERXKVlU1bXoUQ+liA==",
+ "dev": true
+ },
+ "node_modules/@npmcli/promise-spawn": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-1.3.2.tgz",
+ "integrity": "sha512-QyAGYo/Fbj4MXeGdJcFzZ+FkDkomfRBrPM+9QYJSg+PxgAUL+LU3FneQk37rKR2/zjqkCV1BLHccX98wRXG3Sg==",
+ "dev": true,
+ "dependencies": {
+ "infer-owner": "^1.0.4"
+ }
+ },
+ "node_modules/@npmcli/run-script": {
+ "version": "1.8.6",
+ "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-1.8.6.tgz",
+ "integrity": "sha512-e42bVZnC6VluBZBAFEr3YrdqSspG3bgilyg4nSLBJ7TRGNCzxHa92XAHxQBLYg0BmgwO4b2mf3h/l5EkEWRn3g==",
+ "dev": true,
+ "dependencies": {
+ "@npmcli/node-gyp": "^1.0.2",
+ "@npmcli/promise-spawn": "^1.3.2",
+ "node-gyp": "^7.1.0",
+ "read-package-json-fast": "^2.0.1"
+ }
+ },
+ "node_modules/@rollup/plugin-commonjs": {
+ "version": "23.0.2",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-23.0.2.tgz",
+ "integrity": "sha512-e9ThuiRf93YlVxc4qNIurvv+Hp9dnD+4PjOqQs5vAYfcZ3+AXSrcdzXnVjWxcGQOa6KGJFcRZyUI3ktWLavFjg==",
+ "dev": true,
+ "dependencies": {
+ "@rollup/pluginutils": "^5.0.1",
+ "commondir": "^1.0.1",
+ "estree-walker": "^2.0.2",
+ "glob": "^8.0.3",
+ "is-reference": "1.2.1",
+ "magic-string": "^0.26.4"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^2.68.0||^3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "rollup": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@rollup/plugin-commonjs/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/@rollup/plugin-commonjs/node_modules/glob": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz",
+ "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==",
+ "dev": true,
+ "dependencies": {
+ "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/@rollup/plugin-commonjs/node_modules/minimatch": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz",
+ "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@rollup/plugin-node-resolve": {
+ "version": "15.0.1",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.0.1.tgz",
+ "integrity": "sha512-ReY88T7JhJjeRVbfCyNj+NXAG3IIsVMsX9b5/9jC98dRP8/yxlZdz7mHZbHk5zHr24wZZICS5AcXsFZAXYUQEg==",
+ "dev": true,
+ "dependencies": {
+ "@rollup/pluginutils": "^5.0.1",
+ "@types/resolve": "1.20.2",
+ "deepmerge": "^4.2.2",
+ "is-builtin-module": "^3.2.0",
+ "is-module": "^1.0.0",
+ "resolve": "^1.22.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^2.78.0||^3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "rollup": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@rollup/plugin-terser": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.1.0.tgz",
+ "integrity": "sha512-N2KK+qUfHX2hBzVzM41UWGLrEmcjVC37spC8R3c9mt3oEDFKh3N2e12/lLp9aVSt86veR0TQiCNQXrm8C6aiUQ==",
+ "dev": true,
+ "dependencies": {
+ "terser": "^5.15.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^2.x || ^3.x"
+ },
+ "peerDependenciesMeta": {
+ "rollup": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@rollup/plugin-typescript": {
+ "version": "9.0.2",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-9.0.2.tgz",
+ "integrity": "sha512-/sS93vmHUMjzDUsl5scNQr1mUlNE1QjBBvOhmRwJCH8k2RRhDIm3c977B3wdu3t3Ap17W6dDeXP3hj1P1Un1bA==",
+ "dev": true,
+ "dependencies": {
+ "@rollup/pluginutils": "^5.0.1",
+ "resolve": "^1.22.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^2.14.0||^3.0.0",
+ "tslib": "*",
+ "typescript": ">=3.7.0"
+ },
+ "peerDependenciesMeta": {
+ "rollup": {
+ "optional": true
+ },
+ "tslib": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@rollup/pluginutils": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz",
+ "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==",
+ "dev": true,
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "estree-walker": "^2.0.2",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^1.20.0||^2.0.0||^3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "rollup": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@sinclair/typebox": {
+ "version": "0.24.51",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz",
+ "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==",
+ "dev": true
+ },
+ "node_modules/@sinonjs/commons": {
+ "version": "1.8.3",
+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz",
+ "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==",
+ "dev": true,
+ "dependencies": {
+ "type-detect": "4.0.8"
+ }
+ },
+ "node_modules/@sinonjs/fake-timers": {
+ "version": "9.1.2",
+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz",
+ "integrity": "sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==",
+ "dev": true,
+ "dependencies": {
+ "@sinonjs/commons": "^1.7.0"
+ }
+ },
+ "node_modules/@tootallnate/once": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
+ "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.1.19",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz",
+ "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.6.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz",
+ "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.1",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz",
+ "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.18.2",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.2.tgz",
+ "integrity": "sha512-FcFaxOr2V5KZCviw1TnutEMVUVsGt4D2hP1TAfXZAMKuHYW3xQhe3jTxNPWutgCJ3/X1c5yX8ZoGVEItxKbwBg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.3.0"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz",
+ "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==",
+ "dev": true
+ },
+ "node_modules/@types/fs-extra": {
+ "version": "8.1.2",
+ "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.2.tgz",
+ "integrity": "sha512-SvSrYXfWSc7R4eqnOzbQF4TZmfpNSM9FrSWLU3EUnWBuyZqNBOrv1B1JA3byUDPUl9z4Ab3jeZG2eDdySlgNMg==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/glob": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==",
+ "dev": true,
+ "dependencies": {
+ "@types/minimatch": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/graceful-fs": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz",
+ "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "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==",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "@types/istanbul-lib-report": "*"
+ }
+ },
+ "node_modules/@types/jest": {
+ "version": "29.2.1",
+ "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.2.1.tgz",
+ "integrity": "sha512-nKixEdnGDqFOZkMTF74avFNr3yRqB1ZJ6sRZv5/28D5x2oLN14KApv7F9mfDT/vUic0L3tRCsh3XWpWjtJisUQ==",
+ "dev": true,
+ "dependencies": {
+ "expect": "^29.0.0",
+ "pretty-format": "^29.0.0"
+ }
+ },
+ "node_modules/@types/minimatch": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz",
+ "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==",
+ "dev": true
+ },
+ "node_modules/@types/node": {
+ "version": "17.0.22",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.22.tgz",
+ "integrity": "sha512-8FwbVoG4fy+ykY86XCAclKZDORttqE5/s7dyWZKLXTdv3vRy5HozBEinG5IqhvPXXzIZEcTVbuHlQEI6iuwcmw==",
+ "dev": true
+ },
+ "node_modules/@types/prettier": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.1.tgz",
+ "integrity": "sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==",
+ "dev": true
+ },
+ "node_modules/@types/resolve": {
+ "version": "1.20.2",
+ "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
+ "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==",
+ "dev": true
+ },
+ "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==",
+ "dev": true
+ },
+ "node_modules/@types/yargs": {
+ "version": "17.0.13",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz",
+ "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==",
+ "dev": true,
+ "dependencies": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "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==",
+ "dev": true
+ },
+ "node_modules/abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
+ "dev": true
+ },
+ "node_modules/acorn": {
+ "version": "8.8.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz",
+ "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/agentkeepalive": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz",
+ "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^4.1.0",
+ "depd": "^1.1.2",
+ "humanize-ms": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 8.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==",
+ "dev": true,
+ "dependencies": {
+ "clean-stack": "^2.0.0",
+ "indent-string": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "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"
+ }
+ },
+ "node_modules/ansi-align": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz",
+ "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^4.1.0"
+ }
+ },
+ "node_modules/ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.21.3"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
+ "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
+ "dev": true,
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/aproba": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+ "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
+ "dev": true
+ },
+ "node_modules/are-we-there-yet": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz",
+ "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==",
+ "dev": true,
+ "dependencies": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^2.0.6"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "dependencies": {
+ "sprintf-js": "~1.0.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/asn1": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
+ "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
+ "dev": true,
+ "dependencies": {
+ "safer-buffer": "~2.1.0"
+ }
+ },
+ "node_modules/assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+ "dev": true
+ },
+ "node_modules/aws-sign2": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/aws4": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
+ "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==",
+ "dev": true
+ },
+ "node_modules/babel-jest": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.2.2.tgz",
+ "integrity": "sha512-kkq2QSDIuvpgfoac3WZ1OOcHsQQDU5xYk2Ql7tLdJ8BVAYbefEXal+NfS45Y5LVZA7cxC8KYcQMObpCt1J025w==",
+ "dev": true,
+ "dependencies": {
+ "@jest/transform": "^29.2.2",
+ "@types/babel__core": "^7.1.14",
+ "babel-plugin-istanbul": "^6.1.1",
+ "babel-preset-jest": "^29.2.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.8.0"
+ }
+ },
+ "node_modules/babel-plugin-istanbul": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz",
+ "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@istanbuljs/load-nyc-config": "^1.0.0",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-instrument": "^5.0.4",
+ "test-exclude": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/babel-plugin-jest-hoist": {
+ "version": "29.2.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.2.0.tgz",
+ "integrity": "sha512-TnspP2WNiR3GLfCsUNHqeXw0RoQ2f9U5hQ5L3XFpwuO8htQmSrhh8qsB6vi5Yi8+kuynN1yjDjQsPfkebmB6ZA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/template": "^7.3.3",
+ "@babel/types": "^7.3.3",
+ "@types/babel__core": "^7.1.14",
+ "@types/babel__traverse": "^7.0.6"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/babel-preset-current-node-syntax": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz",
+ "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/plugin-syntax-async-generators": "^7.8.4",
+ "@babel/plugin-syntax-bigint": "^7.8.3",
+ "@babel/plugin-syntax-class-properties": "^7.8.3",
+ "@babel/plugin-syntax-import-meta": "^7.8.3",
+ "@babel/plugin-syntax-json-strings": "^7.8.3",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-numeric-separator": "^7.8.3",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-syntax-top-level-await": "^7.8.3"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/babel-preset-jest": {
+ "version": "29.2.0",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.2.0.tgz",
+ "integrity": "sha512-z9JmMJppMxNv8N7fNRHvhMg9cvIkMxQBXgFkane3yKVEvEOP+kB50lk8DFRvF9PGqbyXxlmebKWhuDORO8RgdA==",
+ "dev": true,
+ "dependencies": {
+ "babel-plugin-jest-hoist": "^29.2.0",
+ "babel-preset-current-node-syntax": "^1.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "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"
+ }
+ ]
+ },
+ "node_modules/bcrypt-pbkdf": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+ "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
+ "dev": true,
+ "dependencies": {
+ "tweetnacl": "^0.14.3"
+ }
+ },
+ "node_modules/boxen": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz",
+ "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-align": "^3.0.0",
+ "camelcase": "^6.2.0",
+ "chalk": "^4.1.0",
+ "cli-boxes": "^2.2.1",
+ "string-width": "^4.2.2",
+ "type-fest": "^0.20.2",
+ "widest-line": "^3.1.0",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/boxen/node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/boxen/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==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/brotli-size": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/brotli-size/-/brotli-size-4.0.0.tgz",
+ "integrity": "sha512-uA9fOtlTRC0iqKfzff1W34DXUA3GyVqbUaeo3Rw3d4gd1eavKVCETXrn3NzO74W+UVkG3UHu8WxUi+XvKI/huA==",
+ "dev": true,
+ "dependencies": {
+ "duplexer": "0.1.1"
+ },
+ "engines": {
+ "node": ">= 10.16.0"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.21.4",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz",
+ "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ }
+ ],
+ "dependencies": {
+ "caniuse-lite": "^1.0.30001400",
+ "electron-to-chromium": "^1.4.251",
+ "node-releases": "^2.0.6",
+ "update-browserslist-db": "^1.0.9"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/bs-logger": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz",
+ "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==",
+ "dev": true,
+ "dependencies": {
+ "fast-json-stable-stringify": "2.x"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/bser": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
+ "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
+ "dev": true,
+ "dependencies": {
+ "node-int64": "^0.4.0"
+ }
+ },
+ "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/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,
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/builtins": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz",
+ "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=",
+ "dev": true
+ },
+ "node_modules/cacache": {
+ "version": "15.3.0",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz",
+ "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==",
+ "dev": true,
+ "dependencies": {
+ "@npmcli/fs": "^1.0.0",
+ "@npmcli/move-file": "^1.0.1",
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.0.0",
+ "glob": "^7.1.4",
+ "infer-owner": "^1.0.4",
+ "lru-cache": "^6.0.0",
+ "minipass": "^3.1.1",
+ "minipass-collect": "^1.0.2",
+ "minipass-flush": "^1.0.5",
+ "minipass-pipeline": "^1.2.2",
+ "mkdirp": "^1.0.3",
+ "p-map": "^4.0.0",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^3.0.2",
+ "ssri": "^8.0.1",
+ "tar": "^6.0.2",
+ "unique-filename": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001429",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001429.tgz",
+ "integrity": "sha512-511ThLu1hF+5RRRt0zYCf2U2yRr9GPF6m5y90SBCWsvSoYoW7yAGlv/elyPaNfvGCkp6kj/KFZWU0BMA69Prsg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ }
+ ]
+ },
+ "node_modules/caseless": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
+ "dev": true
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "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/char-regex": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
+ "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/chownr": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+ "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ci-info": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.5.0.tgz",
+ "integrity": "sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==",
+ "dev": true
+ },
+ "node_modules/cjs-module-lexer": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz",
+ "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==",
+ "dev": true
+ },
+ "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"
+ }
+ },
+ "node_modules/cli-boxes": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz",
+ "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==",
+ "dev": true,
+ "engines": {
+ "iojs": ">= 1.0.0",
+ "node": ">= 0.12.0"
+ }
+ },
+ "node_modules/code-point-at": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/collect-v8-coverage": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz",
+ "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "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==",
+ "dev": true
+ },
+ "node_modules/colorette": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz",
+ "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==",
+ "dev": true
+ },
+ "node_modules/colors": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
+ "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.1.90"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "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
+ },
+ "node_modules/commondir": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
+ "dev": true
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "dev": true
+ },
+ "node_modules/console-control-strings": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+ "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
+ "dev": true
+ },
+ "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/core-util-is": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/dashdash": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+ "dev": true,
+ "dependencies": {
+ "assert-plus": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/dedent": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
+ "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==",
+ "dev": true
+ },
+ "node_modules/deepmerge": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
+ "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/delegates": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+ "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
+ "dev": true
+ },
+ "node_modules/depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/detect-newline": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
+ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/diff-sequences": {
+ "version": "29.2.0",
+ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.2.0.tgz",
+ "integrity": "sha512-413SY5JpYeSBZxmenGEmCVQ8mCgtFJF0w9PROdaS6z987XC2Pd2GOKqOITLtMftmyFZqgtCOb/QA7/Z3ZXfzIw==",
+ "dev": true,
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "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,
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/duplexer": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
+ "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
+ "dev": true
+ },
+ "node_modules/ecc-jsbn": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+ "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
+ "dev": true,
+ "dependencies": {
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.1.0"
+ }
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.4.284",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz",
+ "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==",
+ "dev": true
+ },
+ "node_modules/emittery": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz",
+ "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/emittery?sponsor=1"
+ }
+ },
+ "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/encoding": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
+ "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "iconv-lite": "^0.6.2"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/err-code": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz",
+ "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==",
+ "dev": true
+ },
+ "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"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "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==",
+ "dev": true,
+ "engines": {
+ "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==",
+ "dev": true,
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/estree-walker": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
+ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
+ "dev": true
+ },
+ "node_modules/execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/exit": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+ "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/expect": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-29.2.2.tgz",
+ "integrity": "sha512-hE09QerxZ5wXiOhqkXy5d2G9ar+EqOyifnCXCpMNu+vZ6DG9TJ6CO2c2kPDSLqERTTWrO7OZj8EkYHQqSd78Yw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/expect-utils": "^29.2.2",
+ "jest-get-type": "^29.2.0",
+ "jest-matcher-utils": "^29.2.2",
+ "jest-message-util": "^29.2.1",
+ "jest-util": "^29.2.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+ "dev": true
+ },
+ "node_modules/extsprintf": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
+ "dev": true,
+ "engines": [
+ "node >=0.6.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-glob": {
+ "version": "3.2.11",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
+ "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "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/fastq": {
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
+ "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==",
+ "dev": true,
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/fb-watchman": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
+ "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==",
+ "dev": true,
+ "dependencies": {
+ "bser": "2.1.1"
+ }
+ },
+ "node_modules/filesize": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/filesize/-/filesize-6.4.0.tgz",
+ "integrity": "sha512-mjFIpOHC4jbfcTfoh4rkWpI31mF7viw9ikj/JyLoKzqlwG/YsefKfvYlYhdYdg/9mtK2z1AzgN/0LvVQ3zdlSQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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,
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/forever-agent": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/fs-extra": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
+ "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=6 <7 || >=8"
+ }
+ },
+ "node_modules/fs-minipass": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
+ "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+ "dev": true,
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+ "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==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "node_modules/gauge": {
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
+ "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
+ "dev": true,
+ "dependencies": {
+ "aproba": "^1.0.3",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.0",
+ "object-assign": "^4.1.0",
+ "signal-exit": "^3.0.0",
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wide-align": "^1.1.0"
+ }
+ },
+ "node_modules/gauge/node_modules/ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/gauge/node_modules/is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+ "dev": true,
+ "dependencies": {
+ "number-is-nan": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/gauge/node_modules/string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "dev": true,
+ "dependencies": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/gauge/node_modules/strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/getpass": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+ "dev": true,
+ "dependencies": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "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/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/globby": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz",
+ "integrity": "sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==",
+ "dev": true,
+ "dependencies": {
+ "@types/glob": "^7.1.1",
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.0.3",
+ "glob": "^7.1.3",
+ "ignore": "^5.1.1",
+ "merge2": "^1.2.3",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.9",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
+ "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
+ "dev": true
+ },
+ "node_modules/gzip-size": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz",
+ "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==",
+ "dev": true,
+ "dependencies": {
+ "duplexer": "^0.1.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/gzip-size/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/har-schema": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
+ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/har-validator": {
+ "version": "5.1.5",
+ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
+ "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
+ "deprecated": "this library is no longer supported",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^6.12.3",
+ "har-schema": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4.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==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/has-unicode": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+ "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
+ "dev": true
+ },
+ "node_modules/hosted-git-info": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
+ "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "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/http-cache-semantics": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
+ "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==",
+ "dev": true
+ },
+ "node_modules/http-proxy-agent": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
+ "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
+ "dev": true,
+ "dependencies": {
+ "@tootallnate/once": "1",
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/http-signature": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
+ "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+ "dev": true,
+ "dependencies": {
+ "assert-plus": "^1.0.0",
+ "jsprim": "^1.2.2",
+ "sshpk": "^1.7.0"
+ },
+ "engines": {
+ "node": ">=0.8",
+ "npm": ">=1.3.7"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=10.17.0"
+ }
+ },
+ "node_modules/humanize-ms": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
+ "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.0.0"
+ }
+ },
+ "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,
+ "optional": true,
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
+ "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/ignore-walk": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz",
+ "integrity": "sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==",
+ "dev": true,
+ "dependencies": {
+ "minimatch": "^3.0.4"
+ }
+ },
+ "node_modules/import-local": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz",
+ "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==",
+ "dev": true,
+ "dependencies": {
+ "pkg-dir": "^4.2.0",
+ "resolve-cwd": "^3.0.0"
+ },
+ "bin": {
+ "import-local-fixture": "fixtures/cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "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==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/infer-owner": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
+ "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==",
+ "dev": true
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "dev": true,
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "node_modules/ip": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
+ "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=",
+ "dev": true
+ },
+ "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-builtin-module": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.0.tgz",
+ "integrity": "sha512-phDA4oSGt7vl1n5tJvTWooWWAsXLY+2xCnxNqvKhGEzujg+A43wPlPOyDg3C8XQHN+6k/JTQWJ/j0dQh/qr+Hw==",
+ "dev": true,
+ "dependencies": {
+ "builtin-modules": "^3.3.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
+ "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
+ "dev": true,
+ "dependencies": {
+ "has": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-generator-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz",
+ "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "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,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-lambda": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz",
+ "integrity": "sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU=",
+ "dev": true
+ },
+ "node_modules/is-module": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
+ "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=",
+ "dev": true
+ },
+ "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,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-plain-object": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz",
+ "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-reference": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz",
+ "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/estree": "*"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+ "dev": true
+ },
+ "node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+ "dev": true
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
+ "node_modules/isstream": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/istanbul-lib-instrument": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz",
+ "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.12.3",
+ "@babel/parser": "^7.14.7",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=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==",
+ "dev": true,
+ "dependencies": {
+ "istanbul-lib-coverage": "^3.0.0",
+ "make-dir": "^3.0.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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,
+ "dependencies": {
+ "debug": "^4.1.1",
+ "istanbul-lib-coverage": "^3.0.0",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "html-escaper": "^2.0.0",
+ "istanbul-lib-report": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jest": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/jest/-/jest-29.2.2.tgz",
+ "integrity": "sha512-r+0zCN9kUqoON6IjDdjbrsWobXM/09Nd45kIPRD8kloaRh1z5ZCMdVsgLXGxmlL7UpAJsvCYOQNO+NjvG/gqiQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/core": "^29.2.2",
+ "@jest/types": "^29.2.1",
+ "import-local": "^3.0.2",
+ "jest-cli": "^29.2.2"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-changed-files": {
+ "version": "29.2.0",
+ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.2.0.tgz",
+ "integrity": "sha512-qPVmLLyBmvF5HJrY7krDisx6Voi8DmlV3GZYX0aFNbaQsZeoz1hfxcCMbqDGuQCxU1dJy9eYc2xscE8QrCCYaA==",
+ "dev": true,
+ "dependencies": {
+ "execa": "^5.0.0",
+ "p-limit": "^3.1.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-circus": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.2.2.tgz",
+ "integrity": "sha512-upSdWxx+Mh4DV7oueuZndJ1NVdgtTsqM4YgywHEx05UMH5nxxA2Qu9T9T9XVuR021XxqSoaKvSmmpAbjwwwxMw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/environment": "^29.2.2",
+ "@jest/expect": "^29.2.2",
+ "@jest/test-result": "^29.2.1",
+ "@jest/types": "^29.2.1",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "co": "^4.6.0",
+ "dedent": "^0.7.0",
+ "is-generator-fn": "^2.0.0",
+ "jest-each": "^29.2.1",
+ "jest-matcher-utils": "^29.2.2",
+ "jest-message-util": "^29.2.1",
+ "jest-runtime": "^29.2.2",
+ "jest-snapshot": "^29.2.2",
+ "jest-util": "^29.2.1",
+ "p-limit": "^3.1.0",
+ "pretty-format": "^29.2.1",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-cli": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.2.2.tgz",
+ "integrity": "sha512-R45ygnnb2CQOfd8rTPFR+/fls0d+1zXS6JPYTBBrnLPrhr58SSuPTiA5Tplv8/PXpz4zXR/AYNxmwIj6J6nrvg==",
+ "dev": true,
+ "dependencies": {
+ "@jest/core": "^29.2.2",
+ "@jest/test-result": "^29.2.1",
+ "@jest/types": "^29.2.1",
+ "chalk": "^4.0.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "import-local": "^3.0.2",
+ "jest-config": "^29.2.2",
+ "jest-util": "^29.2.1",
+ "jest-validate": "^29.2.2",
+ "prompts": "^2.0.1",
+ "yargs": "^17.3.1"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-config": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.2.2.tgz",
+ "integrity": "sha512-Q0JX54a5g1lP63keRfKR8EuC7n7wwny2HoTRDb8cx78IwQOiaYUVZAdjViY3WcTxpR02rPUpvNVmZ1fkIlZPcw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@jest/test-sequencer": "^29.2.2",
+ "@jest/types": "^29.2.1",
+ "babel-jest": "^29.2.2",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "deepmerge": "^4.2.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "jest-circus": "^29.2.2",
+ "jest-environment-node": "^29.2.2",
+ "jest-get-type": "^29.2.0",
+ "jest-regex-util": "^29.2.0",
+ "jest-resolve": "^29.2.2",
+ "jest-runner": "^29.2.2",
+ "jest-util": "^29.2.1",
+ "jest-validate": "^29.2.2",
+ "micromatch": "^4.0.4",
+ "parse-json": "^5.2.0",
+ "pretty-format": "^29.2.1",
+ "slash": "^3.0.0",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@types/node": "*",
+ "ts-node": ">=9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "ts-node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-diff": {
+ "version": "29.2.1",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.2.1.tgz",
+ "integrity": "sha512-gfh/SMNlQmP3MOUgdzxPOd4XETDJifADpT937fN1iUGz+9DgOu2eUPHH25JDkLVcLwwqxv3GzVyK4VBUr9fjfA==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "diff-sequences": "^29.2.0",
+ "jest-get-type": "^29.2.0",
+ "pretty-format": "^29.2.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-docblock": {
+ "version": "29.2.0",
+ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.2.0.tgz",
+ "integrity": "sha512-bkxUsxTgWQGbXV5IENmfiIuqZhJcyvF7tU4zJ/7ioTutdz4ToB5Yx6JOFBpgI+TphRY4lhOyCWGNH/QFQh5T6A==",
+ "dev": true,
+ "dependencies": {
+ "detect-newline": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-each": {
+ "version": "29.2.1",
+ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.2.1.tgz",
+ "integrity": "sha512-sGP86H/CpWHMyK3qGIGFCgP6mt+o5tu9qG4+tobl0LNdgny0aitLXs9/EBacLy3Bwqy+v4uXClqJgASJWcruYw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.2.1",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.2.0",
+ "jest-util": "^29.2.1",
+ "pretty-format": "^29.2.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-environment-node": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.2.2.tgz",
+ "integrity": "sha512-B7qDxQjkIakQf+YyrqV5dICNs7tlCO55WJ4OMSXsqz1lpI/0PmeuXdx2F7eU8rnPbRkUR/fItSSUh0jvE2y/tw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/environment": "^29.2.2",
+ "@jest/fake-timers": "^29.2.2",
+ "@jest/types": "^29.2.1",
+ "@types/node": "*",
+ "jest-mock": "^29.2.2",
+ "jest-util": "^29.2.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-get-type": {
+ "version": "29.2.0",
+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz",
+ "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==",
+ "dev": true,
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-haste-map": {
+ "version": "29.2.1",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.2.1.tgz",
+ "integrity": "sha512-wF460rAFmYc6ARcCFNw4MbGYQjYkvjovb9GBT+W10Um8q5nHq98jD6fHZMDMO3tA56S8XnmNkM8GcA8diSZfnA==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.2.1",
+ "@types/graceful-fs": "^4.1.3",
+ "@types/node": "*",
+ "anymatch": "^3.0.3",
+ "fb-watchman": "^2.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-regex-util": "^29.2.0",
+ "jest-util": "^29.2.1",
+ "jest-worker": "^29.2.1",
+ "micromatch": "^4.0.4",
+ "walker": "^1.0.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "^2.3.2"
+ }
+ },
+ "node_modules/jest-leak-detector": {
+ "version": "29.2.1",
+ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.2.1.tgz",
+ "integrity": "sha512-1YvSqYoiurxKOJtySc+CGVmw/e1v4yNY27BjWTVzp0aTduQeA7pdieLiW05wTYG/twlKOp2xS/pWuikQEmklug==",
+ "dev": true,
+ "dependencies": {
+ "jest-get-type": "^29.2.0",
+ "pretty-format": "^29.2.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-matcher-utils": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.2.2.tgz",
+ "integrity": "sha512-4DkJ1sDPT+UX2MR7Y3od6KtvRi9Im1ZGLGgdLFLm4lPexbTaCgJW5NN3IOXlQHF7NSHY/VHhflQ+WoKtD/vyCw==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "jest-diff": "^29.2.1",
+ "jest-get-type": "^29.2.0",
+ "pretty-format": "^29.2.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-message-util": {
+ "version": "29.2.1",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.2.1.tgz",
+ "integrity": "sha512-Dx5nEjw9V8C1/Yj10S/8ivA8F439VS8vTq1L7hEgwHFn9ovSKNpYW/kwNh7UglaEgXO42XxzKJB+2x0nSglFVw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.12.13",
+ "@jest/types": "^29.2.1",
+ "@types/stack-utils": "^2.0.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.2.1",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-mock": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.2.2.tgz",
+ "integrity": "sha512-1leySQxNAnivvbcx0sCB37itu8f4OX2S/+gxLAV4Z62shT4r4dTG9tACDywUAEZoLSr36aYUTsVp3WKwWt4PMQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.2.1",
+ "@types/node": "*",
+ "jest-util": "^29.2.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-pnp-resolver": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz",
+ "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ },
+ "peerDependencies": {
+ "jest-resolve": "*"
+ },
+ "peerDependenciesMeta": {
+ "jest-resolve": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-regex-util": {
+ "version": "29.2.0",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.2.0.tgz",
+ "integrity": "sha512-6yXn0kg2JXzH30cr2NlThF+70iuO/3irbaB4mh5WyqNIvLLP+B6sFdluO1/1RJmslyh/f9osnefECflHvTbwVA==",
+ "dev": true,
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-resolve": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.2.2.tgz",
+ "integrity": "sha512-3gaLpiC3kr14rJR3w7vWh0CBX2QAhfpfiQTwrFPvVrcHe5VUBtIXaR004aWE/X9B2CFrITOQAp5gxLONGrk6GA==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.2.1",
+ "jest-pnp-resolver": "^1.2.2",
+ "jest-util": "^29.2.1",
+ "jest-validate": "^29.2.2",
+ "resolve": "^1.20.0",
+ "resolve.exports": "^1.1.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-resolve-dependencies": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.2.2.tgz",
+ "integrity": "sha512-wWOmgbkbIC2NmFsq8Lb+3EkHuW5oZfctffTGvwsA4JcJ1IRk8b2tg+hz44f0lngvRTeHvp3Kyix9ACgudHH9aQ==",
+ "dev": true,
+ "dependencies": {
+ "jest-regex-util": "^29.2.0",
+ "jest-snapshot": "^29.2.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-runner": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.2.2.tgz",
+ "integrity": "sha512-1CpUxXDrbsfy9Hr9/1zCUUhT813kGGK//58HeIw/t8fa/DmkecEwZSWlb1N/xDKXg3uCFHQp1GCvlSClfImMxg==",
+ "dev": true,
+ "dependencies": {
+ "@jest/console": "^29.2.1",
+ "@jest/environment": "^29.2.2",
+ "@jest/test-result": "^29.2.1",
+ "@jest/transform": "^29.2.2",
+ "@jest/types": "^29.2.1",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "graceful-fs": "^4.2.9",
+ "jest-docblock": "^29.2.0",
+ "jest-environment-node": "^29.2.2",
+ "jest-haste-map": "^29.2.1",
+ "jest-leak-detector": "^29.2.1",
+ "jest-message-util": "^29.2.1",
+ "jest-resolve": "^29.2.2",
+ "jest-runtime": "^29.2.2",
+ "jest-util": "^29.2.1",
+ "jest-watcher": "^29.2.2",
+ "jest-worker": "^29.2.1",
+ "p-limit": "^3.1.0",
+ "source-map-support": "0.5.13"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-runner/node_modules/source-map-support": {
+ "version": "0.5.13",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
+ "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==",
+ "dev": true,
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/jest-runtime": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.2.2.tgz",
+ "integrity": "sha512-TpR1V6zRdLynckKDIQaY41od4o0xWL+KOPUCZvJK2bu5P1UXhjobt5nJ2ICNeIxgyj9NGkO0aWgDqYPVhDNKjA==",
+ "dev": true,
+ "dependencies": {
+ "@jest/environment": "^29.2.2",
+ "@jest/fake-timers": "^29.2.2",
+ "@jest/globals": "^29.2.2",
+ "@jest/source-map": "^29.2.0",
+ "@jest/test-result": "^29.2.1",
+ "@jest/transform": "^29.2.2",
+ "@jest/types": "^29.2.1",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "cjs-module-lexer": "^1.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.2.1",
+ "jest-message-util": "^29.2.1",
+ "jest-mock": "^29.2.2",
+ "jest-regex-util": "^29.2.0",
+ "jest-resolve": "^29.2.2",
+ "jest-snapshot": "^29.2.2",
+ "jest-util": "^29.2.1",
+ "slash": "^3.0.0",
+ "strip-bom": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-snapshot": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.2.2.tgz",
+ "integrity": "sha512-GfKJrpZ5SMqhli3NJ+mOspDqtZfJBryGA8RIBxF+G+WbDoC7HCqKaeAss4Z/Sab6bAW11ffasx8/vGsj83jyjA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@babel/generator": "^7.7.2",
+ "@babel/plugin-syntax-jsx": "^7.7.2",
+ "@babel/plugin-syntax-typescript": "^7.7.2",
+ "@babel/traverse": "^7.7.2",
+ "@babel/types": "^7.3.3",
+ "@jest/expect-utils": "^29.2.2",
+ "@jest/transform": "^29.2.2",
+ "@jest/types": "^29.2.1",
+ "@types/babel__traverse": "^7.0.6",
+ "@types/prettier": "^2.1.5",
+ "babel-preset-current-node-syntax": "^1.0.0",
+ "chalk": "^4.0.0",
+ "expect": "^29.2.2",
+ "graceful-fs": "^4.2.9",
+ "jest-diff": "^29.2.1",
+ "jest-get-type": "^29.2.0",
+ "jest-haste-map": "^29.2.1",
+ "jest-matcher-utils": "^29.2.2",
+ "jest-message-util": "^29.2.1",
+ "jest-util": "^29.2.1",
+ "natural-compare": "^1.4.0",
+ "pretty-format": "^29.2.1",
+ "semver": "^7.3.5"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-snapshot/node_modules/semver": {
+ "version": "7.3.8",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
+ "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/jest-util": {
+ "version": "29.2.1",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.2.1.tgz",
+ "integrity": "sha512-P5VWDj25r7kj7kl4pN2rG/RN2c1TLfYYYZYULnS/35nFDjBai+hBeo3MDrYZS7p6IoY3YHZnt2vq4L6mKnLk0g==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.2.1",
+ "@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-validate": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.2.2.tgz",
+ "integrity": "sha512-eJXATaKaSnOuxNfs8CLHgdABFgUrd0TtWS8QckiJ4L/QVDF4KVbZFBBOwCBZHOS0Rc5fOxqngXeGXE3nGQkpQA==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.2.1",
+ "camelcase": "^6.2.0",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.2.0",
+ "leven": "^3.1.0",
+ "pretty-format": "^29.2.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-validate/node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/jest-watcher": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.2.2.tgz",
+ "integrity": "sha512-j2otfqh7mOvMgN2WlJ0n7gIx9XCMWntheYGlBK7+5g3b1Su13/UAK7pdKGyd4kDlrLwtH2QPvRv5oNIxWvsJ1w==",
+ "dev": true,
+ "dependencies": {
+ "@jest/test-result": "^29.2.1",
+ "@jest/types": "^29.2.1",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "jest-util": "^29.2.1",
+ "string-length": "^4.0.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-worker": {
+ "version": "29.2.1",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.2.1.tgz",
+ "integrity": "sha512-ROHTZ+oj7sBrgtv46zZ84uWky71AoYi0vEV9CdEtc1FQunsoAGe5HbQmW76nI5QWdvECVPrSi1MCVUmizSavMg==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*",
+ "jest-util": "^29.2.1",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "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,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "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==",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
+ "dev": true
+ },
+ "node_modules/jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "dev": true,
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "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": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
+ "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
+ "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-stringify-safe": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
+ "dev": true
+ },
+ "node_modules/json5": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
+ "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
+ "dev": true,
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/jsonfile": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
+ "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
+ "dev": true,
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/jsonparse": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
+ "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=",
+ "dev": true,
+ "engines": [
+ "node >= 0.2.0"
+ ]
+ },
+ "node_modules/jsprim": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
+ "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
+ "dev": true,
+ "dependencies": {
+ "assert-plus": "1.0.0",
+ "extsprintf": "1.3.0",
+ "json-schema": "0.4.0",
+ "verror": "1.10.0"
+ },
+ "engines": {
+ "node": ">=0.6.0"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/leven": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
+ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "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/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,
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/lodash.memoize": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
+ "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/magic-string": {
+ "version": "0.26.7",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.7.tgz",
+ "integrity": "sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==",
+ "dev": true,
+ "dependencies": {
+ "sourcemap-codec": "^1.4.8"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "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,
+ "dependencies": {
+ "semver": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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/make-fetch-happen": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz",
+ "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==",
+ "dev": true,
+ "dependencies": {
+ "agentkeepalive": "^4.1.3",
+ "cacache": "^15.2.0",
+ "http-cache-semantics": "^4.1.0",
+ "http-proxy-agent": "^4.0.1",
+ "https-proxy-agent": "^5.0.0",
+ "is-lambda": "^1.0.1",
+ "lru-cache": "^6.0.0",
+ "minipass": "^3.1.3",
+ "minipass-collect": "^1.0.2",
+ "minipass-fetch": "^1.3.2",
+ "minipass-flush": "^1.0.5",
+ "minipass-pipeline": "^1.2.4",
+ "negotiator": "^0.6.2",
+ "promise-retry": "^2.0.1",
+ "socks-proxy-agent": "^6.0.0",
+ "ssri": "^8.0.0"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/makeerror": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
+ "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
+ "dev": true,
+ "dependencies": {
+ "tmpl": "1.0.5"
+ }
+ },
+ "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==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
+ "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==",
+ "dev": true,
+ "dependencies": {
+ "braces": "^3.0.1",
+ "picomatch": "^2.2.3"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "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==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minipass": {
+ "version": "3.1.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz",
+ "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-collect": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz",
+ "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==",
+ "dev": true,
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/minipass-fetch": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz",
+ "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==",
+ "dev": true,
+ "dependencies": {
+ "minipass": "^3.1.0",
+ "minipass-sized": "^1.0.3",
+ "minizlib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "optionalDependencies": {
+ "encoding": "^0.1.12"
+ }
+ },
+ "node_modules/minipass-flush": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz",
+ "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==",
+ "dev": true,
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/minipass-json-stream": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz",
+ "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==",
+ "dev": true,
+ "dependencies": {
+ "jsonparse": "^1.3.1",
+ "minipass": "^3.0.0"
+ }
+ },
+ "node_modules/minipass-pipeline": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz",
+ "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==",
+ "dev": true,
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-sized": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz",
+ "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==",
+ "dev": true,
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minizlib": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
+ "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+ "dev": true,
+ "dependencies": {
+ "minipass": "^3.0.0",
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "dev": true,
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "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==",
+ "dev": true
+ },
+ "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/negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/node-gyp": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-7.1.2.tgz",
+ "integrity": "sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ==",
+ "dev": true,
+ "dependencies": {
+ "env-paths": "^2.2.0",
+ "glob": "^7.1.4",
+ "graceful-fs": "^4.2.3",
+ "nopt": "^5.0.0",
+ "npmlog": "^4.1.2",
+ "request": "^2.88.2",
+ "rimraf": "^3.0.2",
+ "semver": "^7.3.2",
+ "tar": "^6.0.2",
+ "which": "^2.0.2"
+ },
+ "bin": {
+ "node-gyp": "bin/node-gyp.js"
+ },
+ "engines": {
+ "node": ">= 10.12.0"
+ }
+ },
+ "node_modules/node-gyp/node_modules/semver": {
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+ "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/node-int64": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
+ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==",
+ "dev": true
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz",
+ "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==",
+ "dev": true
+ },
+ "node_modules/nopt": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
+ "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
+ "dev": true,
+ "dependencies": {
+ "abbrev": "1"
+ },
+ "bin": {
+ "nopt": "bin/nopt.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npm-bundled": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz",
+ "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==",
+ "dev": true,
+ "dependencies": {
+ "npm-normalize-package-bin": "^1.0.1"
+ }
+ },
+ "node_modules/npm-install-checks": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-4.0.0.tgz",
+ "integrity": "sha512-09OmyDkNLYwqKPOnbI8exiOZU2GVVmQp7tgez2BPi5OZC8M82elDAps7sxC4l//uSUtotWqoEIDwjRvWH4qz8w==",
+ "dev": true,
+ "dependencies": {
+ "semver": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/npm-install-checks/node_modules/semver": {
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+ "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/npm-normalize-package-bin": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",
+ "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==",
+ "dev": true
+ },
+ "node_modules/npm-package-arg": {
+ "version": "8.1.5",
+ "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz",
+ "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==",
+ "dev": true,
+ "dependencies": {
+ "hosted-git-info": "^4.0.1",
+ "semver": "^7.3.4",
+ "validate-npm-package-name": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/npm-package-arg/node_modules/semver": {
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+ "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/npm-packlist": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-2.2.2.tgz",
+ "integrity": "sha512-Jt01acDvJRhJGthnUJVF/w6gumWOZxO7IkpY/lsX9//zqQgnF7OJaxgQXcerd4uQOLu7W5bkb4mChL9mdfm+Zg==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.6",
+ "ignore-walk": "^3.0.3",
+ "npm-bundled": "^1.1.1",
+ "npm-normalize-package-bin": "^1.0.1"
+ },
+ "bin": {
+ "npm-packlist": "bin/index.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/npm-pick-manifest": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-6.1.1.tgz",
+ "integrity": "sha512-dBsdBtORT84S8V8UTad1WlUyKIY9iMsAmqxHbLdeEeBNMLQDlDWWra3wYUx9EBEIiG/YwAy0XyNHDd2goAsfuA==",
+ "dev": true,
+ "dependencies": {
+ "npm-install-checks": "^4.0.0",
+ "npm-normalize-package-bin": "^1.0.1",
+ "npm-package-arg": "^8.1.2",
+ "semver": "^7.3.4"
+ }
+ },
+ "node_modules/npm-pick-manifest/node_modules/semver": {
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+ "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/npm-registry-fetch": {
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-11.0.0.tgz",
+ "integrity": "sha512-jmlgSxoDNuhAtxUIG6pVwwtz840i994dL14FoNVZisrmZW5kWd63IUTNv1m/hyRSGSqWjCUp/YZlS1BJyNp9XA==",
+ "dev": true,
+ "dependencies": {
+ "make-fetch-happen": "^9.0.1",
+ "minipass": "^3.1.3",
+ "minipass-fetch": "^1.3.0",
+ "minipass-json-stream": "^1.0.1",
+ "minizlib": "^2.0.0",
+ "npm-package-arg": "^8.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "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,
+ "dependencies": {
+ "path-key": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/npmlog": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
+ "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
+ "dev": true,
+ "dependencies": {
+ "are-we-there-yet": "~1.1.2",
+ "console-control-strings": "~1.1.0",
+ "gauge": "~2.7.3",
+ "set-blocking": "~2.0.0"
+ }
+ },
+ "node_modules/number-is-nan": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/oauth-sign": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
+ "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "dev": true,
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "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,
+ "dependencies": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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,
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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,
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/p-locate/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,
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-map": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
+ "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+ "dev": true,
+ "dependencies": {
+ "aggregate-error": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pacote": {
+ "version": "11.3.5",
+ "resolved": "https://registry.npmjs.org/pacote/-/pacote-11.3.5.tgz",
+ "integrity": "sha512-fT375Yczn4zi+6Hkk2TBe1x1sP8FgFsEIZ2/iWaXY2r/NkhDJfxbcn5paz1+RTFCyNf+dPnaoBDJoAxXSU8Bkg==",
+ "dev": true,
+ "dependencies": {
+ "@npmcli/git": "^2.1.0",
+ "@npmcli/installed-package-contents": "^1.0.6",
+ "@npmcli/promise-spawn": "^1.2.0",
+ "@npmcli/run-script": "^1.8.2",
+ "cacache": "^15.0.5",
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.1.0",
+ "infer-owner": "^1.0.4",
+ "minipass": "^3.1.3",
+ "mkdirp": "^1.0.3",
+ "npm-package-arg": "^8.0.1",
+ "npm-packlist": "^2.1.4",
+ "npm-pick-manifest": "^6.0.0",
+ "npm-registry-fetch": "^11.0.0",
+ "promise-retry": "^2.0.1",
+ "read-package-json-fast": "^2.0.1",
+ "rimraf": "^3.0.2",
+ "ssri": "^8.0.1",
+ "tar": "^6.1.0"
+ },
+ "bin": {
+ "pacote": "lib/bin.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "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,
+ "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": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/performance-now": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
+ "dev": true
+ },
+ "node_modules/picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+ "dev": true
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pirates": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz",
+ "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "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,
+ "dependencies": {
+ "find-up": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pretty-format": {
+ "version": "29.2.1",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.2.1.tgz",
+ "integrity": "sha512-Y41Sa4aLCtKAXvwuIpTvcFBkyeYp2gdFWzXGA+ZNES3VwURIB165XO/z7CjETwzCCS53MjW/rLMyyqEnTtaOfA==",
+ "dev": true,
+ "dependencies": {
+ "@jest/schemas": "^29.0.0",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.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==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+ "dev": true
+ },
+ "node_modules/promise-inflight": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
+ "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
+ "dev": true
+ },
+ "node_modules/promise-retry": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz",
+ "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==",
+ "dev": true,
+ "dependencies": {
+ "err-code": "^2.0.2",
+ "retry": "^0.12.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "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,
+ "dependencies": {
+ "kleur": "^3.0.3",
+ "sisteransi": "^1.0.5"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/psl": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
+ "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==",
+ "dev": true
+ },
+ "node_modules/punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/qs": {
+ "version": "6.5.3",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
+ "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "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/react-is": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
+ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
+ "dev": true
+ },
+ "node_modules/read-package-json-fast": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz",
+ "integrity": "sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ==",
+ "dev": true,
+ "dependencies": {
+ "json-parse-even-better-errors": "^2.3.0",
+ "npm-normalize-package-bin": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/readable-stream": {
+ "version": "2.3.7",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+ "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+ "dev": true,
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/regenerator-runtime": {
+ "version": "0.13.9",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
+ "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==",
+ "dev": true
+ },
+ "node_modules/request": {
+ "version": "2.88.2",
+ "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
+ "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
+ "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142",
+ "dev": true,
+ "dependencies": {
+ "aws-sign2": "~0.7.0",
+ "aws4": "^1.8.0",
+ "caseless": "~0.12.0",
+ "combined-stream": "~1.0.6",
+ "extend": "~3.0.2",
+ "forever-agent": "~0.6.1",
+ "form-data": "~2.3.2",
+ "har-validator": "~5.1.3",
+ "http-signature": "~1.2.0",
+ "is-typedarray": "~1.0.0",
+ "isstream": "~0.1.2",
+ "json-stringify-safe": "~5.0.1",
+ "mime-types": "~2.1.19",
+ "oauth-sign": "~0.9.0",
+ "performance-now": "^2.1.0",
+ "qs": "~6.5.2",
+ "safe-buffer": "^5.1.2",
+ "tough-cookie": "~2.5.0",
+ "tunnel-agent": "^0.6.0",
+ "uuid": "^3.3.2"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/request/node_modules/form-data": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+ "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+ "dev": true,
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.6",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 0.12"
+ }
+ },
+ "node_modules/request/node_modules/tough-cookie": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
+ "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
+ "dev": true,
+ "dependencies": {
+ "psl": "^1.1.28",
+ "punycode": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "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==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.22.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+ "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+ "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"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-cwd": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+ "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
+ "dev": true,
+ "dependencies": {
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/resolve.exports": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz",
+ "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/retry": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
+ "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.2.5.tgz",
+ "integrity": "sha512-/Ha7HhVVofduy+RKWOQJrxe4Qb3xyZo+chcpYiD8SoQa4AG7llhupUtyfKSSrdBM2mWJjhM8wZwmbY23NmlIYw==",
+ "dev": true,
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=14.18.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/rollup-plugin-base64": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/rollup-plugin-base64/-/rollup-plugin-base64-1.0.1.tgz",
+ "integrity": "sha512-IbdX8fjuXO/Op3hYmRPjVo0VwcSenwsQDaDTFdoe+70B5ZGoLMtr96L2yhHXCfxv7HwZVvxZqLsuWj6VwzRt3g==",
+ "dev": true,
+ "dependencies": {
+ "@rollup/pluginutils": "^3.1.0"
+ }
+ },
+ "node_modules/rollup-plugin-base64/node_modules/@rollup/pluginutils": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz",
+ "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==",
+ "dev": true,
+ "dependencies": {
+ "@types/estree": "0.0.39",
+ "estree-walker": "^1.0.1",
+ "picomatch": "^2.2.2"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^1.20.0||^2.0.0"
+ }
+ },
+ "node_modules/rollup-plugin-base64/node_modules/@types/estree": {
+ "version": "0.0.39",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
+ "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
+ "dev": true
+ },
+ "node_modules/rollup-plugin-base64/node_modules/estree-walker": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz",
+ "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==",
+ "dev": true
+ },
+ "node_modules/rollup-plugin-base64/node_modules/rollup": {
+ "version": "2.79.1",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
+ "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==",
+ "dev": true,
+ "peer": true,
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/rollup-plugin-copy": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/rollup-plugin-copy/-/rollup-plugin-copy-3.4.0.tgz",
+ "integrity": "sha512-rGUmYYsYsceRJRqLVlE9FivJMxJ7X6jDlP79fmFkL8sJs7VVMSVyA2yfyL+PGyO/vJs4A87hwhgVfz61njI+uQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/fs-extra": "^8.0.1",
+ "colorette": "^1.1.0",
+ "fs-extra": "^8.1.0",
+ "globby": "10.0.1",
+ "is-plain-object": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8.3"
+ }
+ },
+ "node_modules/rollup-plugin-filesize": {
+ "version": "9.1.2",
+ "resolved": "https://registry.npmjs.org/rollup-plugin-filesize/-/rollup-plugin-filesize-9.1.2.tgz",
+ "integrity": "sha512-m2fE9hFaKgWKisJzyWXctOFKlgMRelo/58HgeC0lXUK/qykxiqkr6bsrotlvo2bvrwPsjgT7scNdQSr6qtl37A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.13.8",
+ "boxen": "^5.0.0",
+ "brotli-size": "4.0.0",
+ "colors": "1.4.0",
+ "filesize": "^6.1.0",
+ "gzip-size": "^6.0.0",
+ "pacote": "^11.2.7",
+ "terser": "^5.6.0"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "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/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ },
+ "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/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
+ "dev": true
+ },
+ "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,
+ "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,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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/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==",
+ "dev": true,
+ "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,
+ "engines": {
+ "node": ">= 6.0.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/socks": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz",
+ "integrity": "sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==",
+ "dev": true,
+ "dependencies": {
+ "ip": "^1.1.5",
+ "smart-buffer": "^4.2.0"
+ },
+ "engines": {
+ "node": ">= 10.13.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/socks-proxy-agent": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz",
+ "integrity": "sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew==",
+ "dev": true,
+ "dependencies": {
+ "agent-base": "^6.0.2",
+ "debug": "^4.3.1",
+ "socks": "^2.6.1"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "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,
+ "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,
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/sourcemap-codec": {
+ "version": "1.4.8",
+ "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
+ "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
+ "dev": true
+ },
+ "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/sshpk": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz",
+ "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==",
+ "dev": true,
+ "dependencies": {
+ "asn1": "~0.2.3",
+ "assert-plus": "^1.0.0",
+ "bcrypt-pbkdf": "^1.0.0",
+ "dashdash": "^1.12.0",
+ "ecc-jsbn": "~0.1.1",
+ "getpass": "^0.1.1",
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.0.2",
+ "tweetnacl": "~0.14.0"
+ },
+ "bin": {
+ "sshpk-conv": "bin/sshpk-conv",
+ "sshpk-sign": "bin/sshpk-sign",
+ "sshpk-verify": "bin/sshpk-verify"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ssri": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz",
+ "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==",
+ "dev": true,
+ "dependencies": {
+ "minipass": "^3.1.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/stack-utils": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz",
+ "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==",
+ "dev": true,
+ "dependencies": {
+ "escape-string-regexp": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/string-length": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
+ "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==",
+ "dev": true,
+ "dependencies": {
+ "char-regex": "^1.0.2",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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==",
+ "dev": true,
+ "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,
+ "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,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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==",
+ "dev": true,
+ "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,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/tar": {
+ "version": "6.1.11",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz",
+ "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==",
+ "dev": true,
+ "dependencies": {
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.0.0",
+ "minipass": "^3.0.0",
+ "minizlib": "^2.1.1",
+ "mkdirp": "^1.0.3",
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/terser": {
+ "version": "5.15.1",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.1.tgz",
+ "integrity": "sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "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,
+ "dependencies": {
+ "@istanbuljs/schema": "^0.1.2",
+ "glob": "^7.1.4",
+ "minimatch": "^3.0.4"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tmpl": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
+ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
+ "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,
+ "engines": {
+ "node": ">=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,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/ts-jest": {
+ "version": "29.0.3",
+ "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.3.tgz",
+ "integrity": "sha512-Ibygvmuyq1qp/z3yTh9QTwVVAbFdDy/+4BtIQR2sp6baF2SJU/8CKK/hhnGIDY2L90Az2jIqTwZPnN2p+BweiQ==",
+ "dev": true,
+ "dependencies": {
+ "bs-logger": "0.x",
+ "fast-json-stable-stringify": "2.x",
+ "jest-util": "^29.0.0",
+ "json5": "^2.2.1",
+ "lodash.memoize": "4.x",
+ "make-error": "1.x",
+ "semver": "7.x",
+ "yargs-parser": "^21.0.1"
+ },
+ "bin": {
+ "ts-jest": "cli.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": ">=7.0.0-beta.0 <8",
+ "@jest/types": "^29.0.0",
+ "babel-jest": "^29.0.0",
+ "jest": "^29.0.0",
+ "typescript": ">=4.3"
+ },
+ "peerDependenciesMeta": {
+ "@babel/core": {
+ "optional": true
+ },
+ "@jest/types": {
+ "optional": true
+ },
+ "babel-jest": {
+ "optional": true
+ },
+ "esbuild": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ts-jest/node_modules/semver": {
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+ "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
+ "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==",
+ "dev": true
+ },
+ "node_modules/tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/tweetnacl": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
+ "dev": true
+ },
+ "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,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "4.8.4",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz",
+ "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==",
+ "dev": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ },
+ "node_modules/unique-filename": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
+ "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==",
+ "dev": true,
+ "dependencies": {
+ "unique-slug": "^2.0.0"
+ }
+ },
+ "node_modules/unique-slug": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz",
+ "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==",
+ "dev": true,
+ "dependencies": {
+ "imurmurhash": "^0.1.4"
+ }
+ },
+ "node_modules/universalify": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
+ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz",
+ "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ }
+ ],
+ "dependencies": {
+ "escalade": "^3.1.1",
+ "picocolors": "^1.0.0"
+ },
+ "bin": {
+ "browserslist-lint": "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,
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+ "dev": true
+ },
+ "node_modules/uuid": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
+ "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
+ "dev": true,
+ "bin": {
+ "uuid": "bin/uuid"
+ }
+ },
+ "node_modules/v8-to-istanbul": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz",
+ "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.12",
+ "@types/istanbul-lib-coverage": "^2.0.1",
+ "convert-source-map": "^1.6.0"
+ },
+ "engines": {
+ "node": ">=10.12.0"
+ }
+ },
+ "node_modules/validate-npm-package-name": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz",
+ "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=",
+ "dev": true,
+ "dependencies": {
+ "builtins": "^1.0.3"
+ }
+ },
+ "node_modules/verror": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+ "dev": true,
+ "engines": [
+ "node >=0.6.0"
+ ],
+ "dependencies": {
+ "assert-plus": "^1.0.0",
+ "core-util-is": "1.0.2",
+ "extsprintf": "^1.2.0"
+ }
+ },
+ "node_modules/verror/node_modules/core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+ "dev": true
+ },
+ "node_modules/walker": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
+ "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
+ "dev": true,
+ "dependencies": {
+ "makeerror": "1.0.12"
+ }
+ },
+ "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,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/wide-align": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
+ "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^1.0.2 || 2 || 3 || 4"
+ }
+ },
+ "node_modules/widest-line": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz",
+ "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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==",
+ "dev": true,
+ "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": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+ "dev": true
+ },
+ "node_modules/write-file-atomic": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz",
+ "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==",
+ "dev": true,
+ "dependencies": {
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.7"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.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==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "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/yargs": {
+ "version": "17.6.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.0.tgz",
+ "integrity": "sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==",
+ "dev": true,
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ },
+ "dependencies": {
+ "@ampproject/remapping": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
+ "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==",
+ "dev": true,
+ "requires": {
+ "@jridgewell/gen-mapping": "^0.1.0",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ }
+ },
+ "@babel/code-frame": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz",
+ "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.18.6"
+ }
+ },
+ "@babel/compat-data": {
+ "version": "7.20.1",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.1.tgz",
+ "integrity": "sha512-EWZ4mE2diW3QALKvDMiXnbZpRvlj+nayZ112nK93SnhqOtpdsbVD4W+2tEoT3YNBAG9RBR0ISY758ZkOgsn6pQ==",
+ "dev": true
+ },
+ "@babel/core": {
+ "version": "7.19.6",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.6.tgz",
+ "integrity": "sha512-D2Ue4KHpc6Ys2+AxpIx1BZ8+UegLLLE2p3KJEuJRKmokHOtl49jQ5ny1773KsGLZs8MQvBidAF6yWUJxRqtKtg==",
+ "dev": true,
+ "requires": {
+ "@ampproject/remapping": "^2.1.0",
+ "@babel/code-frame": "^7.18.6",
+ "@babel/generator": "^7.19.6",
+ "@babel/helper-compilation-targets": "^7.19.3",
+ "@babel/helper-module-transforms": "^7.19.6",
+ "@babel/helpers": "^7.19.4",
+ "@babel/parser": "^7.19.6",
+ "@babel/template": "^7.18.10",
+ "@babel/traverse": "^7.19.6",
+ "@babel/types": "^7.19.4",
+ "convert-source-map": "^1.7.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.1",
+ "semver": "^6.3.0"
+ }
+ },
+ "@babel/generator": {
+ "version": "7.20.1",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.1.tgz",
+ "integrity": "sha512-u1dMdBUmA7Z0rBB97xh8pIhviK7oItYOkjbsCxTWMknyvbQRBwX7/gn4JXurRdirWMFh+ZtYARqkA6ydogVZpg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.20.0",
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "jsesc": "^2.5.1"
+ },
+ "dependencies": {
+ "@jridgewell/gen-mapping": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
+ "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
+ "dev": true,
+ "requires": {
+ "@jridgewell/set-array": "^1.0.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ }
+ }
+ }
+ },
+ "@babel/helper-compilation-targets": {
+ "version": "7.20.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.0.tgz",
+ "integrity": "sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ==",
+ "dev": true,
+ "requires": {
+ "@babel/compat-data": "^7.20.0",
+ "@babel/helper-validator-option": "^7.18.6",
+ "browserslist": "^4.21.3",
+ "semver": "^6.3.0"
+ }
+ },
+ "@babel/helper-environment-visitor": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz",
+ "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==",
+ "dev": true
+ },
+ "@babel/helper-function-name": {
+ "version": "7.19.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz",
+ "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.18.10",
+ "@babel/types": "^7.19.0"
+ }
+ },
+ "@babel/helper-hoist-variables": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz",
+ "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.18.6"
+ }
+ },
+ "@babel/helper-module-imports": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz",
+ "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.18.6"
+ }
+ },
+ "@babel/helper-module-transforms": {
+ "version": "7.19.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.6.tgz",
+ "integrity": "sha512-fCmcfQo/KYr/VXXDIyd3CBGZ6AFhPFy1TfSEJ+PilGVlQT6jcbqtHAM4C1EciRqMza7/TpOUZliuSH+U6HAhJw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-module-imports": "^7.18.6",
+ "@babel/helper-simple-access": "^7.19.4",
+ "@babel/helper-split-export-declaration": "^7.18.6",
+ "@babel/helper-validator-identifier": "^7.19.1",
+ "@babel/template": "^7.18.10",
+ "@babel/traverse": "^7.19.6",
+ "@babel/types": "^7.19.4"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.19.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz",
+ "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==",
+ "dev": true
+ },
+ "@babel/helper-simple-access": {
+ "version": "7.19.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.19.4.tgz",
+ "integrity": "sha512-f9Xq6WqBFqaDfbCzn2w85hwklswz5qsKlh7f08w4Y9yhJHpnNC0QemtSkK5YyOY8kPGvyiwdzZksGUhnGdaUIg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.19.4"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz",
+ "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.18.6"
+ }
+ },
+ "@babel/helper-string-parser": {
+ "version": "7.19.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz",
+ "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==",
+ "dev": true
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.19.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz",
+ "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==",
+ "dev": true
+ },
+ "@babel/helper-validator-option": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz",
+ "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==",
+ "dev": true
+ },
+ "@babel/helpers": {
+ "version": "7.20.1",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.1.tgz",
+ "integrity": "sha512-J77mUVaDTUJFZ5BpP6mMn6OIl3rEWymk2ZxDBQJUG3P+PbmyMcF3bYWvz0ma69Af1oobDqT/iAsvzhB58xhQUg==",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.18.10",
+ "@babel/traverse": "^7.20.1",
+ "@babel/types": "^7.20.0"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
+ "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ },
+ "dependencies": {
+ "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==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "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,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "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
+ },
+ "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
+ },
+ "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==",
+ "dev": true
+ },
+ "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,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "@babel/parser": {
+ "version": "7.20.1",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.1.tgz",
+ "integrity": "sha512-hp0AYxaZJhxULfM1zyp7Wgr+pSUKBcP3M+PHnSzWGdXOzg/kHWIgiUWARvubhUKGOEw3xqY4x+lyZ9ytBVcELw==",
+ "dev": true
+ },
+ "@babel/plugin-syntax-async-generators": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
+ "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-bigint": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz",
+ "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-class-properties": {
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
+ "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.12.13"
+ }
+ },
+ "@babel/plugin-syntax-import-meta": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
+ "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ }
+ },
+ "@babel/plugin-syntax-json-strings": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+ "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-jsx": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz",
+ "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-syntax-logical-assignment-operators": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+ "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ }
+ },
+ "@babel/plugin-syntax-nullish-coalescing-operator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+ "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-numeric-separator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ }
+ },
+ "@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+ "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-optional-catch-binding": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+ "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-optional-chaining": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-top-level-await": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
+ "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-syntax-typescript": {
+ "version": "7.20.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz",
+ "integrity": "sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.19.0"
+ }
+ },
+ "@babel/runtime": {
+ "version": "7.17.8",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.8.tgz",
+ "integrity": "sha512-dQpEpK0O9o6lj6oPu0gRDbbnk+4LeHlNcBpspf6Olzt3GIX4P1lWF1gS+pHLDFlaJvbR6q7jCfQ08zA4QJBnmA==",
+ "dev": true,
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "@babel/template": {
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz",
+ "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.18.6",
+ "@babel/parser": "^7.18.10",
+ "@babel/types": "^7.18.10"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.20.1",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.1.tgz",
+ "integrity": "sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.18.6",
+ "@babel/generator": "^7.20.1",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-function-name": "^7.19.0",
+ "@babel/helper-hoist-variables": "^7.18.6",
+ "@babel/helper-split-export-declaration": "^7.18.6",
+ "@babel/parser": "^7.20.1",
+ "@babel/types": "^7.20.0",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0"
+ }
+ },
+ "@babel/types": {
+ "version": "7.20.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.0.tgz",
+ "integrity": "sha512-Jlgt3H0TajCW164wkTOTzHkZb075tMQMULzrLUoUeKmO7eFL96GgDxf7/Axhc5CAuKE3KFyVW1p6ysKsi2oXAg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-string-parser": "^7.19.4",
+ "@babel/helper-validator-identifier": "^7.19.1",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "@bcoe/v8-coverage": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
+ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
+ "dev": true
+ },
+ "@gar/promisify": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz",
+ "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==",
+ "dev": true
+ },
+ "@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,
+ "requires": {
+ "camelcase": "^5.3.1",
+ "find-up": "^4.1.0",
+ "get-package-type": "^0.1.0",
+ "js-yaml": "^3.13.1",
+ "resolve-from": "^5.0.0"
+ }
+ },
+ "@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==",
+ "dev": true
+ },
+ "@jest/console": {
+ "version": "29.2.1",
+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.2.1.tgz",
+ "integrity": "sha512-MF8Adcw+WPLZGBiNxn76DOuczG3BhODTcMlDCA4+cFi41OkaY/lyI0XUUhi73F88Y+7IHoGmD80pN5CtxQUdSw==",
+ "dev": true,
+ "requires": {
+ "@jest/types": "^29.2.1",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "jest-message-util": "^29.2.1",
+ "jest-util": "^29.2.1",
+ "slash": "^3.0.0"
+ }
+ },
+ "@jest/core": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.2.2.tgz",
+ "integrity": "sha512-susVl8o2KYLcZhhkvSB+b7xX575CX3TmSvxfeDjpRko7KmT89rHkXj6XkDkNpSeFMBzIENw5qIchO9HC9Sem+A==",
+ "dev": true,
+ "requires": {
+ "@jest/console": "^29.2.1",
+ "@jest/reporters": "^29.2.2",
+ "@jest/test-result": "^29.2.1",
+ "@jest/transform": "^29.2.2",
+ "@jest/types": "^29.2.1",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "jest-changed-files": "^29.2.0",
+ "jest-config": "^29.2.2",
+ "jest-haste-map": "^29.2.1",
+ "jest-message-util": "^29.2.1",
+ "jest-regex-util": "^29.2.0",
+ "jest-resolve": "^29.2.2",
+ "jest-resolve-dependencies": "^29.2.2",
+ "jest-runner": "^29.2.2",
+ "jest-runtime": "^29.2.2",
+ "jest-snapshot": "^29.2.2",
+ "jest-util": "^29.2.1",
+ "jest-validate": "^29.2.2",
+ "jest-watcher": "^29.2.2",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.2.1",
+ "slash": "^3.0.0",
+ "strip-ansi": "^6.0.0"
+ }
+ },
+ "@jest/environment": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.2.2.tgz",
+ "integrity": "sha512-OWn+Vhu0I1yxuGBJEFFekMYc8aGBGrY4rt47SOh/IFaI+D7ZHCk7pKRiSoZ2/Ml7b0Ony3ydmEHRx/tEOC7H1A==",
+ "dev": true,
+ "requires": {
+ "@jest/fake-timers": "^29.2.2",
+ "@jest/types": "^29.2.1",
+ "@types/node": "*",
+ "jest-mock": "^29.2.2"
+ }
+ },
+ "@jest/expect": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.2.2.tgz",
+ "integrity": "sha512-zwblIZnrIVt8z/SiEeJ7Q9wKKuB+/GS4yZe9zw7gMqfGf4C5hBLGrVyxu1SzDbVSqyMSlprKl3WL1r80cBNkgg==",
+ "dev": true,
+ "requires": {
+ "expect": "^29.2.2",
+ "jest-snapshot": "^29.2.2"
+ }
+ },
+ "@jest/expect-utils": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.2.2.tgz",
+ "integrity": "sha512-vwnVmrVhTmGgQzyvcpze08br91OL61t9O0lJMDyb6Y/D8EKQ9V7rGUb/p7PDt0GPzK0zFYqXWFo4EO2legXmkg==",
+ "dev": true,
+ "requires": {
+ "jest-get-type": "^29.2.0"
+ }
+ },
+ "@jest/fake-timers": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.2.2.tgz",
+ "integrity": "sha512-nqaW3y2aSyZDl7zQ7t1XogsxeavNpH6kkdq+EpXncIDvAkjvFD7hmhcIs1nWloengEWUoWqkqSA6MSbf9w6DgA==",
+ "dev": true,
+ "requires": {
+ "@jest/types": "^29.2.1",
+ "@sinonjs/fake-timers": "^9.1.2",
+ "@types/node": "*",
+ "jest-message-util": "^29.2.1",
+ "jest-mock": "^29.2.2",
+ "jest-util": "^29.2.1"
+ }
+ },
+ "@jest/globals": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.2.2.tgz",
+ "integrity": "sha512-/nt+5YMh65kYcfBhj38B3Hm0Trk4IsuMXNDGKE/swp36yydBWfz3OXkLqkSvoAtPW8IJMSJDFCbTM2oj5SNprw==",
+ "dev": true,
+ "requires": {
+ "@jest/environment": "^29.2.2",
+ "@jest/expect": "^29.2.2",
+ "@jest/types": "^29.2.1",
+ "jest-mock": "^29.2.2"
+ }
+ },
+ "@jest/reporters": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.2.2.tgz",
+ "integrity": "sha512-AzjL2rl2zJC0njIzcooBvjA4sJjvdoq98sDuuNs4aNugtLPSQ+91nysGKRF0uY1to5k0MdGMdOBggUsPqvBcpA==",
+ "dev": true,
+ "requires": {
+ "@bcoe/v8-coverage": "^0.2.3",
+ "@jest/console": "^29.2.1",
+ "@jest/test-result": "^29.2.1",
+ "@jest/transform": "^29.2.2",
+ "@jest/types": "^29.2.1",
+ "@jridgewell/trace-mapping": "^0.3.15",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "exit": "^0.1.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "istanbul-lib-coverage": "^3.0.0",
+ "istanbul-lib-instrument": "^5.1.0",
+ "istanbul-lib-report": "^3.0.0",
+ "istanbul-lib-source-maps": "^4.0.0",
+ "istanbul-reports": "^3.1.3",
+ "jest-message-util": "^29.2.1",
+ "jest-util": "^29.2.1",
+ "jest-worker": "^29.2.1",
+ "slash": "^3.0.0",
+ "string-length": "^4.0.1",
+ "strip-ansi": "^6.0.0",
+ "v8-to-istanbul": "^9.0.1"
+ }
+ },
+ "@jest/schemas": {
+ "version": "29.0.0",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.0.0.tgz",
+ "integrity": "sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA==",
+ "dev": true,
+ "requires": {
+ "@sinclair/typebox": "^0.24.1"
+ }
+ },
+ "@jest/source-map": {
+ "version": "29.2.0",
+ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.2.0.tgz",
+ "integrity": "sha512-1NX9/7zzI0nqa6+kgpSdKPK+WU1p+SJk3TloWZf5MzPbxri9UEeXX5bWZAPCzbQcyuAzubcdUHA7hcNznmRqWQ==",
+ "dev": true,
+ "requires": {
+ "@jridgewell/trace-mapping": "^0.3.15",
+ "callsites": "^3.0.0",
+ "graceful-fs": "^4.2.9"
+ }
+ },
+ "@jest/test-result": {
+ "version": "29.2.1",
+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.2.1.tgz",
+ "integrity": "sha512-lS4+H+VkhbX6z64tZP7PAUwPqhwj3kbuEHcaLuaBuB+riyaX7oa1txe0tXgrFj5hRWvZKvqO7LZDlNWeJ7VTPA==",
+ "dev": true,
+ "requires": {
+ "@jest/console": "^29.2.1",
+ "@jest/types": "^29.2.1",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "collect-v8-coverage": "^1.0.0"
+ }
+ },
+ "@jest/test-sequencer": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.2.2.tgz",
+ "integrity": "sha512-Cuc1znc1pl4v9REgmmLf0jBd3Y65UXJpioGYtMr/JNpQEIGEzkmHhy6W6DLbSsXeUA13TDzymPv0ZGZ9jH3eIw==",
+ "dev": true,
+ "requires": {
+ "@jest/test-result": "^29.2.1",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.2.1",
+ "slash": "^3.0.0"
+ }
+ },
+ "@jest/transform": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.2.2.tgz",
+ "integrity": "sha512-aPe6rrletyuEIt2axxgdtxljmzH8O/nrov4byy6pDw9S8inIrTV+2PnjyP/oFHMSynzGxJ2s6OHowBNMXp/Jzg==",
+ "dev": true,
+ "requires": {
+ "@babel/core": "^7.11.6",
+ "@jest/types": "^29.2.1",
+ "@jridgewell/trace-mapping": "^0.3.15",
+ "babel-plugin-istanbul": "^6.1.1",
+ "chalk": "^4.0.0",
+ "convert-source-map": "^1.4.0",
+ "fast-json-stable-stringify": "^2.1.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.2.1",
+ "jest-regex-util": "^29.2.0",
+ "jest-util": "^29.2.1",
+ "micromatch": "^4.0.4",
+ "pirates": "^4.0.4",
+ "slash": "^3.0.0",
+ "write-file-atomic": "^4.0.1"
+ }
+ },
+ "@jest/types": {
+ "version": "29.2.1",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.2.1.tgz",
+ "integrity": "sha512-O/QNDQODLnINEPAI0cl9U6zUIDXEWXt6IC1o2N2QENuos7hlGUIthlKyV4p6ki3TvXFX071blj8HUhgLGquPjw==",
+ "dev": true,
+ "requires": {
+ "@jest/schemas": "^29.0.0",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ }
+ },
+ "@jridgewell/gen-mapping": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
+ "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==",
+ "dev": true,
+ "requires": {
+ "@jridgewell/set-array": "^1.0.0",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
+ "@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==",
+ "dev": true
+ },
+ "@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==",
+ "dev": true
+ },
+ "@jridgewell/source-map": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz",
+ "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==",
+ "dev": true,
+ "requires": {
+ "@jridgewell/gen-mapping": "^0.3.0",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ },
+ "dependencies": {
+ "@jridgewell/gen-mapping": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
+ "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
+ "dev": true,
+ "requires": {
+ "@jridgewell/set-array": "^1.0.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ }
+ }
+ }
+ },
+ "@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
+ },
+ "@jridgewell/trace-mapping": {
+ "version": "0.3.17",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz",
+ "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==",
+ "dev": true,
+ "requires": {
+ "@jridgewell/resolve-uri": "3.1.0",
+ "@jridgewell/sourcemap-codec": "1.4.14"
+ }
+ },
+ "@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,
+ "requires": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ }
+ },
+ "@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true
+ },
+ "@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ }
+ },
+ "@npmcli/fs": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz",
+ "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==",
+ "dev": true,
+ "requires": {
+ "@gar/promisify": "^1.0.1",
+ "semver": "^7.3.5"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+ "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ }
+ }
+ },
+ "@npmcli/git": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-2.1.0.tgz",
+ "integrity": "sha512-/hBFX/QG1b+N7PZBFs0bi+evgRZcK9nWBxQKZkGoXUT5hJSwl5c4d7y8/hm+NQZRPhQ67RzFaj5UM9YeyKoryw==",
+ "dev": true,
+ "requires": {
+ "@npmcli/promise-spawn": "^1.3.2",
+ "lru-cache": "^6.0.0",
+ "mkdirp": "^1.0.4",
+ "npm-pick-manifest": "^6.1.1",
+ "promise-inflight": "^1.0.1",
+ "promise-retry": "^2.0.1",
+ "semver": "^7.3.5",
+ "which": "^2.0.2"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+ "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ }
+ }
+ },
+ "@npmcli/installed-package-contents": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-1.0.7.tgz",
+ "integrity": "sha512-9rufe0wnJusCQoLpV9ZPKIVP55itrM5BxOXs10DmdbRfgWtHy1LDyskbwRnBghuB0PrF7pNPOqREVtpz4HqzKw==",
+ "dev": true,
+ "requires": {
+ "npm-bundled": "^1.1.1",
+ "npm-normalize-package-bin": "^1.0.1"
+ }
+ },
+ "@npmcli/move-file": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz",
+ "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==",
+ "dev": true,
+ "requires": {
+ "mkdirp": "^1.0.4",
+ "rimraf": "^3.0.2"
+ }
+ },
+ "@npmcli/node-gyp": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-1.0.3.tgz",
+ "integrity": "sha512-fnkhw+fmX65kiLqk6E3BFLXNC26rUhK90zVwe2yncPliVT/Qos3xjhTLE59Df8KnPlcwIERXKVlU1bXoUQ+liA==",
+ "dev": true
+ },
+ "@npmcli/promise-spawn": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-1.3.2.tgz",
+ "integrity": "sha512-QyAGYo/Fbj4MXeGdJcFzZ+FkDkomfRBrPM+9QYJSg+PxgAUL+LU3FneQk37rKR2/zjqkCV1BLHccX98wRXG3Sg==",
+ "dev": true,
+ "requires": {
+ "infer-owner": "^1.0.4"
+ }
+ },
+ "@npmcli/run-script": {
+ "version": "1.8.6",
+ "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-1.8.6.tgz",
+ "integrity": "sha512-e42bVZnC6VluBZBAFEr3YrdqSspG3bgilyg4nSLBJ7TRGNCzxHa92XAHxQBLYg0BmgwO4b2mf3h/l5EkEWRn3g==",
+ "dev": true,
+ "requires": {
+ "@npmcli/node-gyp": "^1.0.2",
+ "@npmcli/promise-spawn": "^1.3.2",
+ "node-gyp": "^7.1.0",
+ "read-package-json-fast": "^2.0.1"
+ }
+ },
+ "@rollup/plugin-commonjs": {
+ "version": "23.0.2",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-23.0.2.tgz",
+ "integrity": "sha512-e9ThuiRf93YlVxc4qNIurvv+Hp9dnD+4PjOqQs5vAYfcZ3+AXSrcdzXnVjWxcGQOa6KGJFcRZyUI3ktWLavFjg==",
+ "dev": true,
+ "requires": {
+ "@rollup/pluginutils": "^5.0.1",
+ "commondir": "^1.0.1",
+ "estree-walker": "^2.0.2",
+ "glob": "^8.0.3",
+ "is-reference": "1.2.1",
+ "magic-string": "^0.26.4"
+ },
+ "dependencies": {
+ "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,
+ "requires": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "glob": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz",
+ "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^5.0.1",
+ "once": "^1.3.0"
+ }
+ },
+ "minimatch": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz",
+ "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^2.0.1"
+ }
+ }
+ }
+ },
+ "@rollup/plugin-node-resolve": {
+ "version": "15.0.1",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.0.1.tgz",
+ "integrity": "sha512-ReY88T7JhJjeRVbfCyNj+NXAG3IIsVMsX9b5/9jC98dRP8/yxlZdz7mHZbHk5zHr24wZZICS5AcXsFZAXYUQEg==",
+ "dev": true,
+ "requires": {
+ "@rollup/pluginutils": "^5.0.1",
+ "@types/resolve": "1.20.2",
+ "deepmerge": "^4.2.2",
+ "is-builtin-module": "^3.2.0",
+ "is-module": "^1.0.0",
+ "resolve": "^1.22.1"
+ }
+ },
+ "@rollup/plugin-terser": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.1.0.tgz",
+ "integrity": "sha512-N2KK+qUfHX2hBzVzM41UWGLrEmcjVC37spC8R3c9mt3oEDFKh3N2e12/lLp9aVSt86veR0TQiCNQXrm8C6aiUQ==",
+ "dev": true,
+ "requires": {
+ "terser": "^5.15.1"
+ }
+ },
+ "@rollup/plugin-typescript": {
+ "version": "9.0.2",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-9.0.2.tgz",
+ "integrity": "sha512-/sS93vmHUMjzDUsl5scNQr1mUlNE1QjBBvOhmRwJCH8k2RRhDIm3c977B3wdu3t3Ap17W6dDeXP3hj1P1Un1bA==",
+ "dev": true,
+ "requires": {
+ "@rollup/pluginutils": "^5.0.1",
+ "resolve": "^1.22.1"
+ }
+ },
+ "@rollup/pluginutils": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz",
+ "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==",
+ "dev": true,
+ "requires": {
+ "@types/estree": "^1.0.0",
+ "estree-walker": "^2.0.2",
+ "picomatch": "^2.3.1"
+ }
+ },
+ "@sinclair/typebox": {
+ "version": "0.24.51",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz",
+ "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==",
+ "dev": true
+ },
+ "@sinonjs/commons": {
+ "version": "1.8.3",
+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz",
+ "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==",
+ "dev": true,
+ "requires": {
+ "type-detect": "4.0.8"
+ }
+ },
+ "@sinonjs/fake-timers": {
+ "version": "9.1.2",
+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz",
+ "integrity": "sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==",
+ "dev": true,
+ "requires": {
+ "@sinonjs/commons": "^1.7.0"
+ }
+ },
+ "@tootallnate/once": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
+ "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
+ "dev": true
+ },
+ "@types/babel__core": {
+ "version": "7.1.19",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz",
+ "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==",
+ "dev": true,
+ "requires": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "@types/babel__generator": {
+ "version": "7.6.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz",
+ "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@types/babel__template": {
+ "version": "7.4.1",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz",
+ "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==",
+ "dev": true,
+ "requires": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@types/babel__traverse": {
+ "version": "7.18.2",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.2.tgz",
+ "integrity": "sha512-FcFaxOr2V5KZCviw1TnutEMVUVsGt4D2hP1TAfXZAMKuHYW3xQhe3jTxNPWutgCJ3/X1c5yX8ZoGVEItxKbwBg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.3.0"
+ }
+ },
+ "@types/estree": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz",
+ "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==",
+ "dev": true
+ },
+ "@types/fs-extra": {
+ "version": "8.1.2",
+ "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.2.tgz",
+ "integrity": "sha512-SvSrYXfWSc7R4eqnOzbQF4TZmfpNSM9FrSWLU3EUnWBuyZqNBOrv1B1JA3byUDPUl9z4Ab3jeZG2eDdySlgNMg==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "@types/glob": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==",
+ "dev": true,
+ "requires": {
+ "@types/minimatch": "*",
+ "@types/node": "*"
+ }
+ },
+ "@types/graceful-fs": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz",
+ "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "@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==",
+ "dev": true
+ },
+ "@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==",
+ "dev": true,
+ "requires": {
+ "@types/istanbul-lib-coverage": "*"
+ }
+ },
+ "@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==",
+ "dev": true,
+ "requires": {
+ "@types/istanbul-lib-report": "*"
+ }
+ },
+ "@types/jest": {
+ "version": "29.2.1",
+ "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.2.1.tgz",
+ "integrity": "sha512-nKixEdnGDqFOZkMTF74avFNr3yRqB1ZJ6sRZv5/28D5x2oLN14KApv7F9mfDT/vUic0L3tRCsh3XWpWjtJisUQ==",
+ "dev": true,
+ "requires": {
+ "expect": "^29.0.0",
+ "pretty-format": "^29.0.0"
+ }
+ },
+ "@types/minimatch": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz",
+ "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==",
+ "dev": true
+ },
+ "@types/node": {
+ "version": "17.0.22",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.22.tgz",
+ "integrity": "sha512-8FwbVoG4fy+ykY86XCAclKZDORttqE5/s7dyWZKLXTdv3vRy5HozBEinG5IqhvPXXzIZEcTVbuHlQEI6iuwcmw==",
+ "dev": true
+ },
+ "@types/prettier": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.1.tgz",
+ "integrity": "sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==",
+ "dev": true
+ },
+ "@types/resolve": {
+ "version": "1.20.2",
+ "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
+ "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==",
+ "dev": true
+ },
+ "@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==",
+ "dev": true
+ },
+ "@types/yargs": {
+ "version": "17.0.13",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.13.tgz",
+ "integrity": "sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==",
+ "dev": true,
+ "requires": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "@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==",
+ "dev": true
+ },
+ "abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
+ "dev": true
+ },
+ "acorn": {
+ "version": "8.8.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz",
+ "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "debug": "4"
+ }
+ },
+ "agentkeepalive": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz",
+ "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==",
+ "dev": true,
+ "requires": {
+ "debug": "^4.1.0",
+ "depd": "^1.1.2",
+ "humanize-ms": "^1.2.1"
+ }
+ },
+ "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,
+ "requires": {
+ "clean-stack": "^2.0.0",
+ "indent-string": "^4.0.0"
+ }
+ },
+ "ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ansi-align": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz",
+ "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==",
+ "dev": true,
+ "requires": {
+ "string-width": "^4.1.0"
+ }
+ },
+ "ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.21.3"
+ }
+ },
+ "ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "anymatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
+ "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
+ "dev": true,
+ "requires": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ }
+ },
+ "aproba": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+ "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
+ "dev": true
+ },
+ "are-we-there-yet": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz",
+ "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==",
+ "dev": true,
+ "requires": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^2.0.6"
+ }
+ },
+ "argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "requires": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "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
+ },
+ "asn1": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
+ "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
+ "dev": true,
+ "requires": {
+ "safer-buffer": "~2.1.0"
+ }
+ },
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+ "dev": true
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+ "dev": true
+ },
+ "aws-sign2": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
+ "dev": true
+ },
+ "aws4": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
+ "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==",
+ "dev": true
+ },
+ "babel-jest": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.2.2.tgz",
+ "integrity": "sha512-kkq2QSDIuvpgfoac3WZ1OOcHsQQDU5xYk2Ql7tLdJ8BVAYbefEXal+NfS45Y5LVZA7cxC8KYcQMObpCt1J025w==",
+ "dev": true,
+ "requires": {
+ "@jest/transform": "^29.2.2",
+ "@types/babel__core": "^7.1.14",
+ "babel-plugin-istanbul": "^6.1.1",
+ "babel-preset-jest": "^29.2.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "slash": "^3.0.0"
+ }
+ },
+ "babel-plugin-istanbul": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz",
+ "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@istanbuljs/load-nyc-config": "^1.0.0",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-instrument": "^5.0.4",
+ "test-exclude": "^6.0.0"
+ }
+ },
+ "babel-plugin-jest-hoist": {
+ "version": "29.2.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.2.0.tgz",
+ "integrity": "sha512-TnspP2WNiR3GLfCsUNHqeXw0RoQ2f9U5hQ5L3XFpwuO8htQmSrhh8qsB6vi5Yi8+kuynN1yjDjQsPfkebmB6ZA==",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.3.3",
+ "@babel/types": "^7.3.3",
+ "@types/babel__core": "^7.1.14",
+ "@types/babel__traverse": "^7.0.6"
+ }
+ },
+ "babel-preset-current-node-syntax": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz",
+ "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==",
+ "dev": true,
+ "requires": {
+ "@babel/plugin-syntax-async-generators": "^7.8.4",
+ "@babel/plugin-syntax-bigint": "^7.8.3",
+ "@babel/plugin-syntax-class-properties": "^7.8.3",
+ "@babel/plugin-syntax-import-meta": "^7.8.3",
+ "@babel/plugin-syntax-json-strings": "^7.8.3",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-numeric-separator": "^7.8.3",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-syntax-top-level-await": "^7.8.3"
+ }
+ },
+ "babel-preset-jest": {
+ "version": "29.2.0",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.2.0.tgz",
+ "integrity": "sha512-z9JmMJppMxNv8N7fNRHvhMg9cvIkMxQBXgFkane3yKVEvEOP+kB50lk8DFRvF9PGqbyXxlmebKWhuDORO8RgdA==",
+ "dev": true,
+ "requires": {
+ "babel-plugin-jest-hoist": "^29.2.0",
+ "babel-preset-current-node-syntax": "^1.0.0"
+ }
+ },
+ "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
+ },
+ "base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
+ },
+ "bcrypt-pbkdf": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+ "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
+ "dev": true,
+ "requires": {
+ "tweetnacl": "^0.14.3"
+ }
+ },
+ "boxen": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz",
+ "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==",
+ "dev": true,
+ "requires": {
+ "ansi-align": "^3.0.0",
+ "camelcase": "^6.2.0",
+ "chalk": "^4.1.0",
+ "cli-boxes": "^2.2.1",
+ "string-width": "^4.2.2",
+ "type-fest": "^0.20.2",
+ "widest-line": "^3.1.0",
+ "wrap-ansi": "^7.0.0"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "dev": true
+ },
+ "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==",
+ "dev": true
+ }
+ }
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
+ "brotli-size": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/brotli-size/-/brotli-size-4.0.0.tgz",
+ "integrity": "sha512-uA9fOtlTRC0iqKfzff1W34DXUA3GyVqbUaeo3Rw3d4gd1eavKVCETXrn3NzO74W+UVkG3UHu8WxUi+XvKI/huA==",
+ "dev": true,
+ "requires": {
+ "duplexer": "0.1.1"
+ }
+ },
+ "browserslist": {
+ "version": "4.21.4",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz",
+ "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==",
+ "dev": true,
+ "requires": {
+ "caniuse-lite": "^1.0.30001400",
+ "electron-to-chromium": "^1.4.251",
+ "node-releases": "^2.0.6",
+ "update-browserslist-db": "^1.0.9"
+ }
+ },
+ "bs-logger": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz",
+ "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==",
+ "dev": true,
+ "requires": {
+ "fast-json-stable-stringify": "2.x"
+ }
+ },
+ "bser": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
+ "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
+ "dev": true,
+ "requires": {
+ "node-int64": "^0.4.0"
+ }
+ },
+ "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
+ },
+ "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
+ },
+ "builtins": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz",
+ "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=",
+ "dev": true
+ },
+ "cacache": {
+ "version": "15.3.0",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz",
+ "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==",
+ "dev": true,
+ "requires": {
+ "@npmcli/fs": "^1.0.0",
+ "@npmcli/move-file": "^1.0.1",
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.0.0",
+ "glob": "^7.1.4",
+ "infer-owner": "^1.0.4",
+ "lru-cache": "^6.0.0",
+ "minipass": "^3.1.1",
+ "minipass-collect": "^1.0.2",
+ "minipass-flush": "^1.0.5",
+ "minipass-pipeline": "^1.2.2",
+ "mkdirp": "^1.0.3",
+ "p-map": "^4.0.0",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^3.0.2",
+ "ssri": "^8.0.1",
+ "tar": "^6.0.2",
+ "unique-filename": "^1.1.1"
+ }
+ },
+ "callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true
+ },
+ "camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true
+ },
+ "caniuse-lite": {
+ "version": "1.0.30001429",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001429.tgz",
+ "integrity": "sha512-511ThLu1hF+5RRRt0zYCf2U2yRr9GPF6m5y90SBCWsvSoYoW7yAGlv/elyPaNfvGCkp6kj/KFZWU0BMA69Prsg==",
+ "dev": true
+ },
+ "caseless": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "char-regex": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
+ "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
+ "dev": true
+ },
+ "chownr": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+ "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+ "dev": true
+ },
+ "ci-info": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.5.0.tgz",
+ "integrity": "sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==",
+ "dev": true
+ },
+ "cjs-module-lexer": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz",
+ "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==",
+ "dev": true
+ },
+ "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
+ },
+ "cli-boxes": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz",
+ "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==",
+ "dev": true
+ },
+ "cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dev": true,
+ "requires": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ }
+ },
+ "co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==",
+ "dev": true
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
+ "dev": true
+ },
+ "collect-v8-coverage": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz",
+ "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "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==",
+ "dev": true
+ },
+ "colorette": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz",
+ "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==",
+ "dev": true
+ },
+ "colors": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
+ "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
+ "dev": true
+ },
+ "combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dev": true,
+ "requires": {
+ "delayed-stream": "~1.0.0"
+ }
+ },
+ "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
+ },
+ "commondir": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "dev": true
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+ "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
+ "dev": true
+ },
+ "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
+ },
+ "core-util-is": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
+ "dev": true
+ },
+ "cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ }
+ },
+ "dashdash": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "dedent": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
+ "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==",
+ "dev": true
+ },
+ "deepmerge": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
+ "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
+ "dev": true
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+ "dev": true
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+ "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
+ "dev": true
+ },
+ "depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
+ "dev": true
+ },
+ "detect-newline": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
+ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==",
+ "dev": true
+ },
+ "diff-sequences": {
+ "version": "29.2.0",
+ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.2.0.tgz",
+ "integrity": "sha512-413SY5JpYeSBZxmenGEmCVQ8mCgtFJF0w9PROdaS6z987XC2Pd2GOKqOITLtMftmyFZqgtCOb/QA7/Z3ZXfzIw==",
+ "dev": true
+ },
+ "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,
+ "requires": {
+ "path-type": "^4.0.0"
+ }
+ },
+ "duplexer": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
+ "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
+ "dev": true
+ },
+ "ecc-jsbn": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+ "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
+ "dev": true,
+ "requires": {
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.1.0"
+ }
+ },
+ "electron-to-chromium": {
+ "version": "1.4.284",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz",
+ "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==",
+ "dev": true
+ },
+ "emittery": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz",
+ "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==",
+ "dev": true
+ },
+ "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
+ },
+ "encoding": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
+ "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "iconv-lite": "^0.6.2"
+ }
+ },
+ "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
+ },
+ "err-code": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz",
+ "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==",
+ "dev": true
+ },
+ "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,
+ "requires": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+ "dev": true
+ },
+ "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==",
+ "dev": true
+ },
+ "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
+ },
+ "estree-walker": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
+ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
+ "dev": true
+ },
+ "execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+ "dev": true,
+ "requires": {
+ "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"
+ }
+ },
+ "exit": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+ "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==",
+ "dev": true
+ },
+ "expect": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-29.2.2.tgz",
+ "integrity": "sha512-hE09QerxZ5wXiOhqkXy5d2G9ar+EqOyifnCXCpMNu+vZ6DG9TJ6CO2c2kPDSLqERTTWrO7OZj8EkYHQqSd78Yw==",
+ "dev": true,
+ "requires": {
+ "@jest/expect-utils": "^29.2.2",
+ "jest-get-type": "^29.2.0",
+ "jest-matcher-utils": "^29.2.2",
+ "jest-message-util": "^29.2.1",
+ "jest-util": "^29.2.1"
+ }
+ },
+ "extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+ "dev": true
+ },
+ "extsprintf": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
+ "dev": true
+ },
+ "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
+ },
+ "fast-glob": {
+ "version": "3.2.11",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
+ "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==",
+ "dev": true,
+ "requires": {
+ "@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"
+ }
+ },
+ "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
+ },
+ "fastq": {
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
+ "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==",
+ "dev": true,
+ "requires": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "fb-watchman": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
+ "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==",
+ "dev": true,
+ "requires": {
+ "bser": "2.1.1"
+ }
+ },
+ "filesize": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/filesize/-/filesize-6.4.0.tgz",
+ "integrity": "sha512-mjFIpOHC4jbfcTfoh4rkWpI31mF7viw9ikj/JyLoKzqlwG/YsefKfvYlYhdYdg/9mtK2z1AzgN/0LvVQ3zdlSQ==",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "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,
+ "requires": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ }
+ },
+ "forever-agent": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
+ "dev": true
+ },
+ "fs-extra": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
+ "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ }
+ },
+ "fs-minipass": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
+ "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+ "dev": true,
+ "requires": {
+ "minipass": "^3.0.0"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+ "dev": true
+ },
+ "fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
+ "optional": true
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "gauge": {
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
+ "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
+ "dev": true,
+ "requires": {
+ "aproba": "^1.0.3",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.0",
+ "object-assign": "^4.1.0",
+ "signal-exit": "^3.0.0",
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wide-align": "^1.1.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+ "dev": true,
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "dev": true,
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ }
+ }
+ },
+ "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
+ },
+ "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==",
+ "dev": true
+ },
+ "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
+ },
+ "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
+ },
+ "getpass": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "glob": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
+ "dev": true,
+ "requires": {
+ "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"
+ }
+ },
+ "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,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ },
+ "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
+ },
+ "globby": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz",
+ "integrity": "sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==",
+ "dev": true,
+ "requires": {
+ "@types/glob": "^7.1.1",
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.0.3",
+ "glob": "^7.1.3",
+ "ignore": "^5.1.1",
+ "merge2": "^1.2.3",
+ "slash": "^3.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.9",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
+ "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
+ "dev": true
+ },
+ "gzip-size": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz",
+ "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==",
+ "dev": true,
+ "requires": {
+ "duplexer": "^0.1.2"
+ },
+ "dependencies": {
+ "duplexer": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
+ "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==",
+ "dev": true
+ }
+ }
+ },
+ "har-schema": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
+ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
+ "dev": true
+ },
+ "har-validator": {
+ "version": "5.1.5",
+ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
+ "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.12.3",
+ "har-schema": "^2.0.0"
+ }
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+ "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
+ "dev": true
+ },
+ "hosted-git-info": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
+ "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
+ "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
+ },
+ "http-cache-semantics": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
+ "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==",
+ "dev": true
+ },
+ "http-proxy-agent": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
+ "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
+ "dev": true,
+ "requires": {
+ "@tootallnate/once": "1",
+ "agent-base": "6",
+ "debug": "4"
+ }
+ },
+ "http-signature": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
+ "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "jsprim": "^1.2.2",
+ "sshpk": "^1.7.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "agent-base": "6",
+ "debug": "4"
+ }
+ },
+ "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
+ },
+ "humanize-ms": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
+ "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=",
+ "dev": true,
+ "requires": {
+ "ms": "^2.0.0"
+ }
+ },
+ "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,
+ "optional": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ }
+ },
+ "ignore": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
+ "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
+ "dev": true
+ },
+ "ignore-walk": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz",
+ "integrity": "sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==",
+ "dev": true,
+ "requires": {
+ "minimatch": "^3.0.4"
+ }
+ },
+ "import-local": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz",
+ "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==",
+ "dev": true,
+ "requires": {
+ "pkg-dir": "^4.2.0",
+ "resolve-cwd": "^3.0.0"
+ }
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+ "dev": true
+ },
+ "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==",
+ "dev": true
+ },
+ "infer-owner": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
+ "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==",
+ "dev": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "dev": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "ip": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
+ "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=",
+ "dev": true
+ },
+ "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
+ },
+ "is-builtin-module": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.0.tgz",
+ "integrity": "sha512-phDA4oSGt7vl1n5tJvTWooWWAsXLY+2xCnxNqvKhGEzujg+A43wPlPOyDg3C8XQHN+6k/JTQWJ/j0dQh/qr+Hw==",
+ "dev": true,
+ "requires": {
+ "builtin-modules": "^3.3.0"
+ }
+ },
+ "is-core-module": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
+ "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.3"
+ }
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "dev": true
+ },
+ "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==",
+ "dev": true
+ },
+ "is-generator-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz",
+ "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==",
+ "dev": true
+ },
+ "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,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-lambda": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz",
+ "integrity": "sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU=",
+ "dev": true
+ },
+ "is-module": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
+ "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=",
+ "dev": true
+ },
+ "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
+ },
+ "is-plain-object": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz",
+ "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==",
+ "dev": true
+ },
+ "is-reference": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz",
+ "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==",
+ "dev": true,
+ "requires": {
+ "@types/estree": "*"
+ }
+ },
+ "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
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+ "dev": true
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+ "dev": true
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
+ "isstream": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
+ "dev": true
+ },
+ "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==",
+ "dev": true
+ },
+ "istanbul-lib-instrument": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz",
+ "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==",
+ "dev": true,
+ "requires": {
+ "@babel/core": "^7.12.3",
+ "@babel/parser": "^7.14.7",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^6.3.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "istanbul-lib-coverage": "^3.0.0",
+ "make-dir": "^3.0.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "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,
+ "requires": {
+ "debug": "^4.1.1",
+ "istanbul-lib-coverage": "^3.0.0",
+ "source-map": "^0.6.1"
+ }
+ },
+ "istanbul-reports": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz",
+ "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==",
+ "dev": true,
+ "requires": {
+ "html-escaper": "^2.0.0",
+ "istanbul-lib-report": "^3.0.0"
+ }
+ },
+ "jest": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/jest/-/jest-29.2.2.tgz",
+ "integrity": "sha512-r+0zCN9kUqoON6IjDdjbrsWobXM/09Nd45kIPRD8kloaRh1z5ZCMdVsgLXGxmlL7UpAJsvCYOQNO+NjvG/gqiQ==",
+ "dev": true,
+ "requires": {
+ "@jest/core": "^29.2.2",
+ "@jest/types": "^29.2.1",
+ "import-local": "^3.0.2",
+ "jest-cli": "^29.2.2"
+ }
+ },
+ "jest-changed-files": {
+ "version": "29.2.0",
+ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.2.0.tgz",
+ "integrity": "sha512-qPVmLLyBmvF5HJrY7krDisx6Voi8DmlV3GZYX0aFNbaQsZeoz1hfxcCMbqDGuQCxU1dJy9eYc2xscE8QrCCYaA==",
+ "dev": true,
+ "requires": {
+ "execa": "^5.0.0",
+ "p-limit": "^3.1.0"
+ }
+ },
+ "jest-circus": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.2.2.tgz",
+ "integrity": "sha512-upSdWxx+Mh4DV7oueuZndJ1NVdgtTsqM4YgywHEx05UMH5nxxA2Qu9T9T9XVuR021XxqSoaKvSmmpAbjwwwxMw==",
+ "dev": true,
+ "requires": {
+ "@jest/environment": "^29.2.2",
+ "@jest/expect": "^29.2.2",
+ "@jest/test-result": "^29.2.1",
+ "@jest/types": "^29.2.1",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "co": "^4.6.0",
+ "dedent": "^0.7.0",
+ "is-generator-fn": "^2.0.0",
+ "jest-each": "^29.2.1",
+ "jest-matcher-utils": "^29.2.2",
+ "jest-message-util": "^29.2.1",
+ "jest-runtime": "^29.2.2",
+ "jest-snapshot": "^29.2.2",
+ "jest-util": "^29.2.1",
+ "p-limit": "^3.1.0",
+ "pretty-format": "^29.2.1",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
+ }
+ },
+ "jest-cli": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.2.2.tgz",
+ "integrity": "sha512-R45ygnnb2CQOfd8rTPFR+/fls0d+1zXS6JPYTBBrnLPrhr58SSuPTiA5Tplv8/PXpz4zXR/AYNxmwIj6J6nrvg==",
+ "dev": true,
+ "requires": {
+ "@jest/core": "^29.2.2",
+ "@jest/test-result": "^29.2.1",
+ "@jest/types": "^29.2.1",
+ "chalk": "^4.0.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "import-local": "^3.0.2",
+ "jest-config": "^29.2.2",
+ "jest-util": "^29.2.1",
+ "jest-validate": "^29.2.2",
+ "prompts": "^2.0.1",
+ "yargs": "^17.3.1"
+ }
+ },
+ "jest-config": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.2.2.tgz",
+ "integrity": "sha512-Q0JX54a5g1lP63keRfKR8EuC7n7wwny2HoTRDb8cx78IwQOiaYUVZAdjViY3WcTxpR02rPUpvNVmZ1fkIlZPcw==",
+ "dev": true,
+ "requires": {
+ "@babel/core": "^7.11.6",
+ "@jest/test-sequencer": "^29.2.2",
+ "@jest/types": "^29.2.1",
+ "babel-jest": "^29.2.2",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "deepmerge": "^4.2.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "jest-circus": "^29.2.2",
+ "jest-environment-node": "^29.2.2",
+ "jest-get-type": "^29.2.0",
+ "jest-regex-util": "^29.2.0",
+ "jest-resolve": "^29.2.2",
+ "jest-runner": "^29.2.2",
+ "jest-util": "^29.2.1",
+ "jest-validate": "^29.2.2",
+ "micromatch": "^4.0.4",
+ "parse-json": "^5.2.0",
+ "pretty-format": "^29.2.1",
+ "slash": "^3.0.0",
+ "strip-json-comments": "^3.1.1"
+ }
+ },
+ "jest-diff": {
+ "version": "29.2.1",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.2.1.tgz",
+ "integrity": "sha512-gfh/SMNlQmP3MOUgdzxPOd4XETDJifADpT937fN1iUGz+9DgOu2eUPHH25JDkLVcLwwqxv3GzVyK4VBUr9fjfA==",
+ "dev": true,
+ "requires": {
+ "chalk": "^4.0.0",
+ "diff-sequences": "^29.2.0",
+ "jest-get-type": "^29.2.0",
+ "pretty-format": "^29.2.1"
+ }
+ },
+ "jest-docblock": {
+ "version": "29.2.0",
+ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.2.0.tgz",
+ "integrity": "sha512-bkxUsxTgWQGbXV5IENmfiIuqZhJcyvF7tU4zJ/7ioTutdz4ToB5Yx6JOFBpgI+TphRY4lhOyCWGNH/QFQh5T6A==",
+ "dev": true,
+ "requires": {
+ "detect-newline": "^3.0.0"
+ }
+ },
+ "jest-each": {
+ "version": "29.2.1",
+ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.2.1.tgz",
+ "integrity": "sha512-sGP86H/CpWHMyK3qGIGFCgP6mt+o5tu9qG4+tobl0LNdgny0aitLXs9/EBacLy3Bwqy+v4uXClqJgASJWcruYw==",
+ "dev": true,
+ "requires": {
+ "@jest/types": "^29.2.1",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.2.0",
+ "jest-util": "^29.2.1",
+ "pretty-format": "^29.2.1"
+ }
+ },
+ "jest-environment-node": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.2.2.tgz",
+ "integrity": "sha512-B7qDxQjkIakQf+YyrqV5dICNs7tlCO55WJ4OMSXsqz1lpI/0PmeuXdx2F7eU8rnPbRkUR/fItSSUh0jvE2y/tw==",
+ "dev": true,
+ "requires": {
+ "@jest/environment": "^29.2.2",
+ "@jest/fake-timers": "^29.2.2",
+ "@jest/types": "^29.2.1",
+ "@types/node": "*",
+ "jest-mock": "^29.2.2",
+ "jest-util": "^29.2.1"
+ }
+ },
+ "jest-get-type": {
+ "version": "29.2.0",
+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz",
+ "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==",
+ "dev": true
+ },
+ "jest-haste-map": {
+ "version": "29.2.1",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.2.1.tgz",
+ "integrity": "sha512-wF460rAFmYc6ARcCFNw4MbGYQjYkvjovb9GBT+W10Um8q5nHq98jD6fHZMDMO3tA56S8XnmNkM8GcA8diSZfnA==",
+ "dev": true,
+ "requires": {
+ "@jest/types": "^29.2.1",
+ "@types/graceful-fs": "^4.1.3",
+ "@types/node": "*",
+ "anymatch": "^3.0.3",
+ "fb-watchman": "^2.0.0",
+ "fsevents": "^2.3.2",
+ "graceful-fs": "^4.2.9",
+ "jest-regex-util": "^29.2.0",
+ "jest-util": "^29.2.1",
+ "jest-worker": "^29.2.1",
+ "micromatch": "^4.0.4",
+ "walker": "^1.0.8"
+ }
+ },
+ "jest-leak-detector": {
+ "version": "29.2.1",
+ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.2.1.tgz",
+ "integrity": "sha512-1YvSqYoiurxKOJtySc+CGVmw/e1v4yNY27BjWTVzp0aTduQeA7pdieLiW05wTYG/twlKOp2xS/pWuikQEmklug==",
+ "dev": true,
+ "requires": {
+ "jest-get-type": "^29.2.0",
+ "pretty-format": "^29.2.1"
+ }
+ },
+ "jest-matcher-utils": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.2.2.tgz",
+ "integrity": "sha512-4DkJ1sDPT+UX2MR7Y3od6KtvRi9Im1ZGLGgdLFLm4lPexbTaCgJW5NN3IOXlQHF7NSHY/VHhflQ+WoKtD/vyCw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^4.0.0",
+ "jest-diff": "^29.2.1",
+ "jest-get-type": "^29.2.0",
+ "pretty-format": "^29.2.1"
+ }
+ },
+ "jest-message-util": {
+ "version": "29.2.1",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.2.1.tgz",
+ "integrity": "sha512-Dx5nEjw9V8C1/Yj10S/8ivA8F439VS8vTq1L7hEgwHFn9ovSKNpYW/kwNh7UglaEgXO42XxzKJB+2x0nSglFVw==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.12.13",
+ "@jest/types": "^29.2.1",
+ "@types/stack-utils": "^2.0.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.2.1",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
+ }
+ },
+ "jest-mock": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.2.2.tgz",
+ "integrity": "sha512-1leySQxNAnivvbcx0sCB37itu8f4OX2S/+gxLAV4Z62shT4r4dTG9tACDywUAEZoLSr36aYUTsVp3WKwWt4PMQ==",
+ "dev": true,
+ "requires": {
+ "@jest/types": "^29.2.1",
+ "@types/node": "*",
+ "jest-util": "^29.2.1"
+ }
+ },
+ "jest-pnp-resolver": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz",
+ "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==",
+ "dev": true,
+ "requires": {}
+ },
+ "jest-regex-util": {
+ "version": "29.2.0",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.2.0.tgz",
+ "integrity": "sha512-6yXn0kg2JXzH30cr2NlThF+70iuO/3irbaB4mh5WyqNIvLLP+B6sFdluO1/1RJmslyh/f9osnefECflHvTbwVA==",
+ "dev": true
+ },
+ "jest-resolve": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.2.2.tgz",
+ "integrity": "sha512-3gaLpiC3kr14rJR3w7vWh0CBX2QAhfpfiQTwrFPvVrcHe5VUBtIXaR004aWE/X9B2CFrITOQAp5gxLONGrk6GA==",
+ "dev": true,
+ "requires": {
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.2.1",
+ "jest-pnp-resolver": "^1.2.2",
+ "jest-util": "^29.2.1",
+ "jest-validate": "^29.2.2",
+ "resolve": "^1.20.0",
+ "resolve.exports": "^1.1.0",
+ "slash": "^3.0.0"
+ }
+ },
+ "jest-resolve-dependencies": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.2.2.tgz",
+ "integrity": "sha512-wWOmgbkbIC2NmFsq8Lb+3EkHuW5oZfctffTGvwsA4JcJ1IRk8b2tg+hz44f0lngvRTeHvp3Kyix9ACgudHH9aQ==",
+ "dev": true,
+ "requires": {
+ "jest-regex-util": "^29.2.0",
+ "jest-snapshot": "^29.2.2"
+ }
+ },
+ "jest-runner": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.2.2.tgz",
+ "integrity": "sha512-1CpUxXDrbsfy9Hr9/1zCUUhT813kGGK//58HeIw/t8fa/DmkecEwZSWlb1N/xDKXg3uCFHQp1GCvlSClfImMxg==",
+ "dev": true,
+ "requires": {
+ "@jest/console": "^29.2.1",
+ "@jest/environment": "^29.2.2",
+ "@jest/test-result": "^29.2.1",
+ "@jest/transform": "^29.2.2",
+ "@jest/types": "^29.2.1",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "graceful-fs": "^4.2.9",
+ "jest-docblock": "^29.2.0",
+ "jest-environment-node": "^29.2.2",
+ "jest-haste-map": "^29.2.1",
+ "jest-leak-detector": "^29.2.1",
+ "jest-message-util": "^29.2.1",
+ "jest-resolve": "^29.2.2",
+ "jest-runtime": "^29.2.2",
+ "jest-util": "^29.2.1",
+ "jest-watcher": "^29.2.2",
+ "jest-worker": "^29.2.1",
+ "p-limit": "^3.1.0",
+ "source-map-support": "0.5.13"
+ },
+ "dependencies": {
+ "source-map-support": {
+ "version": "0.5.13",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
+ "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==",
+ "dev": true,
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ }
+ }
+ },
+ "jest-runtime": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.2.2.tgz",
+ "integrity": "sha512-TpR1V6zRdLynckKDIQaY41od4o0xWL+KOPUCZvJK2bu5P1UXhjobt5nJ2ICNeIxgyj9NGkO0aWgDqYPVhDNKjA==",
+ "dev": true,
+ "requires": {
+ "@jest/environment": "^29.2.2",
+ "@jest/fake-timers": "^29.2.2",
+ "@jest/globals": "^29.2.2",
+ "@jest/source-map": "^29.2.0",
+ "@jest/test-result": "^29.2.1",
+ "@jest/transform": "^29.2.2",
+ "@jest/types": "^29.2.1",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "cjs-module-lexer": "^1.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.2.1",
+ "jest-message-util": "^29.2.1",
+ "jest-mock": "^29.2.2",
+ "jest-regex-util": "^29.2.0",
+ "jest-resolve": "^29.2.2",
+ "jest-snapshot": "^29.2.2",
+ "jest-util": "^29.2.1",
+ "slash": "^3.0.0",
+ "strip-bom": "^4.0.0"
+ }
+ },
+ "jest-snapshot": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.2.2.tgz",
+ "integrity": "sha512-GfKJrpZ5SMqhli3NJ+mOspDqtZfJBryGA8RIBxF+G+WbDoC7HCqKaeAss4Z/Sab6bAW11ffasx8/vGsj83jyjA==",
+ "dev": true,
+ "requires": {
+ "@babel/core": "^7.11.6",
+ "@babel/generator": "^7.7.2",
+ "@babel/plugin-syntax-jsx": "^7.7.2",
+ "@babel/plugin-syntax-typescript": "^7.7.2",
+ "@babel/traverse": "^7.7.2",
+ "@babel/types": "^7.3.3",
+ "@jest/expect-utils": "^29.2.2",
+ "@jest/transform": "^29.2.2",
+ "@jest/types": "^29.2.1",
+ "@types/babel__traverse": "^7.0.6",
+ "@types/prettier": "^2.1.5",
+ "babel-preset-current-node-syntax": "^1.0.0",
+ "chalk": "^4.0.0",
+ "expect": "^29.2.2",
+ "graceful-fs": "^4.2.9",
+ "jest-diff": "^29.2.1",
+ "jest-get-type": "^29.2.0",
+ "jest-haste-map": "^29.2.1",
+ "jest-matcher-utils": "^29.2.2",
+ "jest-message-util": "^29.2.1",
+ "jest-util": "^29.2.1",
+ "natural-compare": "^1.4.0",
+ "pretty-format": "^29.2.1",
+ "semver": "^7.3.5"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "7.3.8",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
+ "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ }
+ }
+ },
+ "jest-util": {
+ "version": "29.2.1",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.2.1.tgz",
+ "integrity": "sha512-P5VWDj25r7kj7kl4pN2rG/RN2c1TLfYYYZYULnS/35nFDjBai+hBeo3MDrYZS7p6IoY3YHZnt2vq4L6mKnLk0g==",
+ "dev": true,
+ "requires": {
+ "@jest/types": "^29.2.1",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
+ }
+ },
+ "jest-validate": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.2.2.tgz",
+ "integrity": "sha512-eJXATaKaSnOuxNfs8CLHgdABFgUrd0TtWS8QckiJ4L/QVDF4KVbZFBBOwCBZHOS0Rc5fOxqngXeGXE3nGQkpQA==",
+ "dev": true,
+ "requires": {
+ "@jest/types": "^29.2.1",
+ "camelcase": "^6.2.0",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.2.0",
+ "leven": "^3.1.0",
+ "pretty-format": "^29.2.1"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "dev": true
+ }
+ }
+ },
+ "jest-watcher": {
+ "version": "29.2.2",
+ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.2.2.tgz",
+ "integrity": "sha512-j2otfqh7mOvMgN2WlJ0n7gIx9XCMWntheYGlBK7+5g3b1Su13/UAK7pdKGyd4kDlrLwtH2QPvRv5oNIxWvsJ1w==",
+ "dev": true,
+ "requires": {
+ "@jest/test-result": "^29.2.1",
+ "@jest/types": "^29.2.1",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "jest-util": "^29.2.1",
+ "string-length": "^4.0.1"
+ }
+ },
+ "jest-worker": {
+ "version": "29.2.1",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.2.1.tgz",
+ "integrity": "sha512-ROHTZ+oj7sBrgtv46zZ84uWky71AoYi0vEV9CdEtc1FQunsoAGe5HbQmW76nI5QWdvECVPrSi1MCVUmizSavMg==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*",
+ "jest-util": "^29.2.1",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "dependencies": {
+ "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,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
+ "js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ }
+ },
+ "jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
+ "dev": true
+ },
+ "jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "dev": true
+ },
+ "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
+ },
+ "json-schema": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
+ "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
+ "dev": true
+ },
+ "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
+ },
+ "json-stringify-safe": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
+ "dev": true
+ },
+ "json5": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
+ "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
+ "dev": true
+ },
+ "jsonfile": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
+ "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "jsonparse": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
+ "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=",
+ "dev": true
+ },
+ "jsprim": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
+ "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
+ "dev": true,
+ "requires": {
+ "assert-plus": "1.0.0",
+ "extsprintf": "1.3.0",
+ "json-schema": "0.4.0",
+ "verror": "1.10.0"
+ }
+ },
+ "kleur": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
+ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
+ "dev": true
+ },
+ "leven": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
+ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
+ "dev": true
+ },
+ "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
+ },
+ "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,
+ "requires": {
+ "p-locate": "^4.1.0"
+ }
+ },
+ "lodash.memoize": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
+ "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
+ "magic-string": {
+ "version": "0.26.7",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.7.tgz",
+ "integrity": "sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==",
+ "dev": true,
+ "requires": {
+ "sourcemap-codec": "^1.4.8"
+ }
+ },
+ "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,
+ "requires": {
+ "semver": "^6.0.0"
+ }
+ },
+ "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
+ },
+ "make-fetch-happen": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz",
+ "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==",
+ "dev": true,
+ "requires": {
+ "agentkeepalive": "^4.1.3",
+ "cacache": "^15.2.0",
+ "http-cache-semantics": "^4.1.0",
+ "http-proxy-agent": "^4.0.1",
+ "https-proxy-agent": "^5.0.0",
+ "is-lambda": "^1.0.1",
+ "lru-cache": "^6.0.0",
+ "minipass": "^3.1.3",
+ "minipass-collect": "^1.0.2",
+ "minipass-fetch": "^1.3.2",
+ "minipass-flush": "^1.0.5",
+ "minipass-pipeline": "^1.2.4",
+ "negotiator": "^0.6.2",
+ "promise-retry": "^2.0.1",
+ "socks-proxy-agent": "^6.0.0",
+ "ssri": "^8.0.0"
+ }
+ },
+ "makeerror": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
+ "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
+ "dev": true,
+ "requires": {
+ "tmpl": "1.0.5"
+ }
+ },
+ "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
+ },
+ "merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true
+ },
+ "micromatch": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
+ "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==",
+ "dev": true,
+ "requires": {
+ "braces": "^3.0.1",
+ "picomatch": "^2.2.3"
+ }
+ },
+ "mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "mime-db": "1.52.0"
+ }
+ },
+ "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
+ },
+ "minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minipass": {
+ "version": "3.1.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz",
+ "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
+ "minipass-collect": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz",
+ "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==",
+ "dev": true,
+ "requires": {
+ "minipass": "^3.0.0"
+ }
+ },
+ "minipass-fetch": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz",
+ "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==",
+ "dev": true,
+ "requires": {
+ "encoding": "^0.1.12",
+ "minipass": "^3.1.0",
+ "minipass-sized": "^1.0.3",
+ "minizlib": "^2.0.0"
+ }
+ },
+ "minipass-flush": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz",
+ "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==",
+ "dev": true,
+ "requires": {
+ "minipass": "^3.0.0"
+ }
+ },
+ "minipass-json-stream": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz",
+ "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==",
+ "dev": true,
+ "requires": {
+ "jsonparse": "^1.3.1",
+ "minipass": "^3.0.0"
+ }
+ },
+ "minipass-pipeline": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz",
+ "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==",
+ "dev": true,
+ "requires": {
+ "minipass": "^3.0.0"
+ }
+ },
+ "minipass-sized": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz",
+ "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==",
+ "dev": true,
+ "requires": {
+ "minipass": "^3.0.0"
+ }
+ },
+ "minizlib": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
+ "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+ "dev": true,
+ "requires": {
+ "minipass": "^3.0.0",
+ "yallist": "^4.0.0"
+ }
+ },
+ "mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
+ "negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "dev": true
+ },
+ "node-gyp": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-7.1.2.tgz",
+ "integrity": "sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ==",
+ "dev": true,
+ "requires": {
+ "env-paths": "^2.2.0",
+ "glob": "^7.1.4",
+ "graceful-fs": "^4.2.3",
+ "nopt": "^5.0.0",
+ "npmlog": "^4.1.2",
+ "request": "^2.88.2",
+ "rimraf": "^3.0.2",
+ "semver": "^7.3.2",
+ "tar": "^6.0.2",
+ "which": "^2.0.2"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+ "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ }
+ }
+ },
+ "node-int64": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
+ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==",
+ "dev": true
+ },
+ "node-releases": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz",
+ "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==",
+ "dev": true
+ },
+ "nopt": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
+ "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
+ "dev": true,
+ "requires": {
+ "abbrev": "1"
+ }
+ },
+ "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
+ },
+ "npm-bundled": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz",
+ "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==",
+ "dev": true,
+ "requires": {
+ "npm-normalize-package-bin": "^1.0.1"
+ }
+ },
+ "npm-install-checks": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-4.0.0.tgz",
+ "integrity": "sha512-09OmyDkNLYwqKPOnbI8exiOZU2GVVmQp7tgez2BPi5OZC8M82elDAps7sxC4l//uSUtotWqoEIDwjRvWH4qz8w==",
+ "dev": true,
+ "requires": {
+ "semver": "^7.1.1"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+ "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ }
+ }
+ },
+ "npm-normalize-package-bin": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",
+ "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==",
+ "dev": true
+ },
+ "npm-package-arg": {
+ "version": "8.1.5",
+ "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz",
+ "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^4.0.1",
+ "semver": "^7.3.4",
+ "validate-npm-package-name": "^3.0.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+ "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ }
+ }
+ },
+ "npm-packlist": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-2.2.2.tgz",
+ "integrity": "sha512-Jt01acDvJRhJGthnUJVF/w6gumWOZxO7IkpY/lsX9//zqQgnF7OJaxgQXcerd4uQOLu7W5bkb4mChL9mdfm+Zg==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.6",
+ "ignore-walk": "^3.0.3",
+ "npm-bundled": "^1.1.1",
+ "npm-normalize-package-bin": "^1.0.1"
+ }
+ },
+ "npm-pick-manifest": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-6.1.1.tgz",
+ "integrity": "sha512-dBsdBtORT84S8V8UTad1WlUyKIY9iMsAmqxHbLdeEeBNMLQDlDWWra3wYUx9EBEIiG/YwAy0XyNHDd2goAsfuA==",
+ "dev": true,
+ "requires": {
+ "npm-install-checks": "^4.0.0",
+ "npm-normalize-package-bin": "^1.0.1",
+ "npm-package-arg": "^8.1.2",
+ "semver": "^7.3.4"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+ "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ }
+ }
+ },
+ "npm-registry-fetch": {
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-11.0.0.tgz",
+ "integrity": "sha512-jmlgSxoDNuhAtxUIG6pVwwtz840i994dL14FoNVZisrmZW5kWd63IUTNv1m/hyRSGSqWjCUp/YZlS1BJyNp9XA==",
+ "dev": true,
+ "requires": {
+ "make-fetch-happen": "^9.0.1",
+ "minipass": "^3.1.3",
+ "minipass-fetch": "^1.3.0",
+ "minipass-json-stream": "^1.0.1",
+ "minizlib": "^2.0.0",
+ "npm-package-arg": "^8.0.0"
+ }
+ },
+ "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,
+ "requires": {
+ "path-key": "^3.0.0"
+ }
+ },
+ "npmlog": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
+ "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
+ "dev": true,
+ "requires": {
+ "are-we-there-yet": "~1.1.2",
+ "console-control-strings": "~1.1.0",
+ "gauge": "~2.7.3",
+ "set-blocking": "~2.0.0"
+ }
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
+ "dev": true
+ },
+ "oauth-sign": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
+ "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
+ "dev": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+ "dev": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dev": true,
+ "requires": {
+ "mimic-fn": "^2.1.0"
+ }
+ },
+ "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,
+ "requires": {
+ "yocto-queue": "^0.1.0"
+ }
+ },
+ "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,
+ "requires": {
+ "p-limit": "^2.2.0"
+ },
+ "dependencies": {
+ "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,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ }
+ }
+ },
+ "p-map": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
+ "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+ "dev": true,
+ "requires": {
+ "aggregate-error": "^3.0.0"
+ }
+ },
+ "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
+ },
+ "pacote": {
+ "version": "11.3.5",
+ "resolved": "https://registry.npmjs.org/pacote/-/pacote-11.3.5.tgz",
+ "integrity": "sha512-fT375Yczn4zi+6Hkk2TBe1x1sP8FgFsEIZ2/iWaXY2r/NkhDJfxbcn5paz1+RTFCyNf+dPnaoBDJoAxXSU8Bkg==",
+ "dev": true,
+ "requires": {
+ "@npmcli/git": "^2.1.0",
+ "@npmcli/installed-package-contents": "^1.0.6",
+ "@npmcli/promise-spawn": "^1.2.0",
+ "@npmcli/run-script": "^1.8.2",
+ "cacache": "^15.0.5",
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.1.0",
+ "infer-owner": "^1.0.4",
+ "minipass": "^3.1.3",
+ "mkdirp": "^1.0.3",
+ "npm-package-arg": "^8.0.1",
+ "npm-packlist": "^2.1.4",
+ "npm-pick-manifest": "^6.0.0",
+ "npm-registry-fetch": "^11.0.0",
+ "promise-retry": "^2.0.1",
+ "read-package-json-fast": "^2.0.1",
+ "rimraf": "^3.0.2",
+ "ssri": "^8.0.1",
+ "tar": "^6.1.0"
+ }
+ },
+ "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,
+ "requires": {
+ "@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"
+ }
+ },
+ "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
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "dev": true
+ },
+ "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
+ },
+ "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
+ },
+ "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
+ },
+ "performance-now": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
+ "dev": true
+ },
+ "picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+ "dev": true
+ },
+ "picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true
+ },
+ "pirates": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz",
+ "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==",
+ "dev": true
+ },
+ "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,
+ "requires": {
+ "find-up": "^4.0.0"
+ }
+ },
+ "pretty-format": {
+ "version": "29.2.1",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.2.1.tgz",
+ "integrity": "sha512-Y41Sa4aLCtKAXvwuIpTvcFBkyeYp2gdFWzXGA+ZNES3VwURIB165XO/z7CjETwzCCS53MjW/rLMyyqEnTtaOfA==",
+ "dev": true,
+ "requires": {
+ "@jest/schemas": "^29.0.0",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "dependencies": {
+ "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
+ }
+ }
+ },
+ "process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+ "dev": true
+ },
+ "promise-inflight": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
+ "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
+ "dev": true
+ },
+ "promise-retry": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz",
+ "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==",
+ "dev": true,
+ "requires": {
+ "err-code": "^2.0.2",
+ "retry": "^0.12.0"
+ }
+ },
+ "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,
+ "requires": {
+ "kleur": "^3.0.3",
+ "sisteransi": "^1.0.5"
+ }
+ },
+ "psl": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
+ "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==",
+ "dev": true
+ },
+ "punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true
+ },
+ "qs": {
+ "version": "6.5.3",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
+ "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==",
+ "dev": true
+ },
+ "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
+ },
+ "react-is": {
+ "version": "18.2.0",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
+ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
+ "dev": true
+ },
+ "read-package-json-fast": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz",
+ "integrity": "sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ==",
+ "dev": true,
+ "requires": {
+ "json-parse-even-better-errors": "^2.3.0",
+ "npm-normalize-package-bin": "^1.0.1"
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.7",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+ "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+ "dev": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.9",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
+ "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==",
+ "dev": true
+ },
+ "request": {
+ "version": "2.88.2",
+ "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
+ "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
+ "dev": true,
+ "requires": {
+ "aws-sign2": "~0.7.0",
+ "aws4": "^1.8.0",
+ "caseless": "~0.12.0",
+ "combined-stream": "~1.0.6",
+ "extend": "~3.0.2",
+ "forever-agent": "~0.6.1",
+ "form-data": "~2.3.2",
+ "har-validator": "~5.1.3",
+ "http-signature": "~1.2.0",
+ "is-typedarray": "~1.0.0",
+ "isstream": "~0.1.2",
+ "json-stringify-safe": "~5.0.1",
+ "mime-types": "~2.1.19",
+ "oauth-sign": "~0.9.0",
+ "performance-now": "^2.1.0",
+ "qs": "~6.5.2",
+ "safe-buffer": "^5.1.2",
+ "tough-cookie": "~2.5.0",
+ "tunnel-agent": "^0.6.0",
+ "uuid": "^3.3.2"
+ },
+ "dependencies": {
+ "form-data": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+ "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+ "dev": true,
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.6",
+ "mime-types": "^2.1.12"
+ }
+ },
+ "tough-cookie": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
+ "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
+ "dev": true,
+ "requires": {
+ "psl": "^1.1.28",
+ "punycode": "^2.1.1"
+ }
+ }
+ }
+ },
+ "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==",
+ "dev": true
+ },
+ "resolve": {
+ "version": "1.22.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+ "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+ "dev": true,
+ "requires": {
+ "is-core-module": "^2.9.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ }
+ },
+ "resolve-cwd": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+ "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
+ "dev": true,
+ "requires": {
+ "resolve-from": "^5.0.0"
+ }
+ },
+ "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
+ },
+ "resolve.exports": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz",
+ "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==",
+ "dev": true
+ },
+ "retry": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
+ "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=",
+ "dev": true
+ },
+ "reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "rollup": {
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.2.5.tgz",
+ "integrity": "sha512-/Ha7HhVVofduy+RKWOQJrxe4Qb3xyZo+chcpYiD8SoQa4AG7llhupUtyfKSSrdBM2mWJjhM8wZwmbY23NmlIYw==",
+ "dev": true,
+ "requires": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "rollup-plugin-base64": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/rollup-plugin-base64/-/rollup-plugin-base64-1.0.1.tgz",
+ "integrity": "sha512-IbdX8fjuXO/Op3hYmRPjVo0VwcSenwsQDaDTFdoe+70B5ZGoLMtr96L2yhHXCfxv7HwZVvxZqLsuWj6VwzRt3g==",
+ "dev": true,
+ "requires": {
+ "@rollup/pluginutils": "^3.1.0"
+ },
+ "dependencies": {
+ "@rollup/pluginutils": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz",
+ "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==",
+ "dev": true,
+ "requires": {
+ "@types/estree": "0.0.39",
+ "estree-walker": "^1.0.1",
+ "picomatch": "^2.2.2"
+ }
+ },
+ "@types/estree": {
+ "version": "0.0.39",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
+ "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
+ "dev": true
+ },
+ "estree-walker": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz",
+ "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==",
+ "dev": true
+ },
+ "rollup": {
+ "version": "2.79.1",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
+ "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "fsevents": "~2.3.2"
+ }
+ }
+ }
+ },
+ "rollup-plugin-copy": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/rollup-plugin-copy/-/rollup-plugin-copy-3.4.0.tgz",
+ "integrity": "sha512-rGUmYYsYsceRJRqLVlE9FivJMxJ7X6jDlP79fmFkL8sJs7VVMSVyA2yfyL+PGyO/vJs4A87hwhgVfz61njI+uQ==",
+ "dev": true,
+ "requires": {
+ "@types/fs-extra": "^8.0.1",
+ "colorette": "^1.1.0",
+ "fs-extra": "^8.1.0",
+ "globby": "10.0.1",
+ "is-plain-object": "^3.0.0"
+ }
+ },
+ "rollup-plugin-filesize": {
+ "version": "9.1.2",
+ "resolved": "https://registry.npmjs.org/rollup-plugin-filesize/-/rollup-plugin-filesize-9.1.2.tgz",
+ "integrity": "sha512-m2fE9hFaKgWKisJzyWXctOFKlgMRelo/58HgeC0lXUK/qykxiqkr6bsrotlvo2bvrwPsjgT7scNdQSr6qtl37A==",
+ "dev": true,
+ "requires": {
+ "@babel/runtime": "^7.13.8",
+ "boxen": "^5.0.0",
+ "brotli-size": "4.0.0",
+ "colors": "1.4.0",
+ "filesize": "^6.1.0",
+ "gzip-size": "^6.0.0",
+ "pacote": "^11.2.7",
+ "terser": "^5.6.0"
+ }
+ },
+ "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,
+ "requires": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
+ "dev": true
+ },
+ "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,
+ "requires": {
+ "shebang-regex": "^3.0.0"
+ }
+ },
+ "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
+ },
+ "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
+ },
+ "sisteransi": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
+ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
+ "dev": true
+ },
+ "slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true
+ },
+ "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
+ },
+ "socks": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz",
+ "integrity": "sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==",
+ "dev": true,
+ "requires": {
+ "ip": "^1.1.5",
+ "smart-buffer": "^4.2.0"
+ }
+ },
+ "socks-proxy-agent": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz",
+ "integrity": "sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew==",
+ "dev": true,
+ "requires": {
+ "agent-base": "^6.0.2",
+ "debug": "^4.3.1",
+ "socks": "^2.6.1"
+ }
+ },
+ "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
+ },
+ "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,
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "sourcemap-codec": {
+ "version": "1.4.8",
+ "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
+ "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
+ "dev": true
+ },
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
+ "dev": true
+ },
+ "sshpk": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz",
+ "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==",
+ "dev": true,
+ "requires": {
+ "asn1": "~0.2.3",
+ "assert-plus": "^1.0.0",
+ "bcrypt-pbkdf": "^1.0.0",
+ "dashdash": "^1.12.0",
+ "ecc-jsbn": "~0.1.1",
+ "getpass": "^0.1.1",
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.0.2",
+ "tweetnacl": "~0.14.0"
+ }
+ },
+ "ssri": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz",
+ "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==",
+ "dev": true,
+ "requires": {
+ "minipass": "^3.1.1"
+ }
+ },
+ "stack-utils": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz",
+ "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==",
+ "dev": true,
+ "requires": {
+ "escape-string-regexp": "^2.0.0"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "string-length": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
+ "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==",
+ "dev": true,
+ "requires": {
+ "char-regex": "^1.0.2",
+ "strip-ansi": "^6.0.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ }
+ },
+ "strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.1"
+ }
+ },
+ "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
+ },
+ "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
+ },
+ "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
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ },
+ "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
+ },
+ "tar": {
+ "version": "6.1.11",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz",
+ "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==",
+ "dev": true,
+ "requires": {
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.0.0",
+ "minipass": "^3.0.0",
+ "minizlib": "^2.1.1",
+ "mkdirp": "^1.0.3",
+ "yallist": "^4.0.0"
+ }
+ },
+ "terser": {
+ "version": "5.15.1",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.1.tgz",
+ "integrity": "sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw==",
+ "dev": true,
+ "requires": {
+ "@jridgewell/source-map": "^0.3.2",
+ "acorn": "^8.5.0",
+ "commander": "^2.20.0",
+ "source-map-support": "~0.5.20"
+ }
+ },
+ "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,
+ "requires": {
+ "@istanbuljs/schema": "^0.1.2",
+ "glob": "^7.1.4",
+ "minimatch": "^3.0.4"
+ }
+ },
+ "tmpl": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
+ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
+ "dev": true
+ },
+ "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
+ },
+ "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,
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ },
+ "ts-jest": {
+ "version": "29.0.3",
+ "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.3.tgz",
+ "integrity": "sha512-Ibygvmuyq1qp/z3yTh9QTwVVAbFdDy/+4BtIQR2sp6baF2SJU/8CKK/hhnGIDY2L90Az2jIqTwZPnN2p+BweiQ==",
+ "dev": true,
+ "requires": {
+ "bs-logger": "0.x",
+ "fast-json-stable-stringify": "2.x",
+ "jest-util": "^29.0.0",
+ "json5": "^2.2.1",
+ "lodash.memoize": "4.x",
+ "make-error": "1.x",
+ "semver": "7.x",
+ "yargs-parser": "^21.0.1"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+ "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ }
+ }
+ },
+ "tslib": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
+ "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==",
+ "dev": true
+ },
+ "tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "tweetnacl": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
+ "dev": true
+ },
+ "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
+ },
+ "type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "dev": true
+ },
+ "typescript": {
+ "version": "4.8.4",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz",
+ "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==",
+ "dev": true
+ },
+ "unique-filename": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
+ "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==",
+ "dev": true,
+ "requires": {
+ "unique-slug": "^2.0.0"
+ }
+ },
+ "unique-slug": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz",
+ "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==",
+ "dev": true,
+ "requires": {
+ "imurmurhash": "^0.1.4"
+ }
+ },
+ "universalify": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
+ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
+ "dev": true
+ },
+ "update-browserslist-db": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz",
+ "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==",
+ "dev": true,
+ "requires": {
+ "escalade": "^3.1.1",
+ "picocolors": "^1.0.0"
+ }
+ },
+ "uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+ "dev": true
+ },
+ "uuid": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
+ "dev": true
+ },
+ "v8-to-istanbul": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz",
+ "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==",
+ "dev": true,
+ "requires": {
+ "@jridgewell/trace-mapping": "^0.3.12",
+ "@types/istanbul-lib-coverage": "^2.0.1",
+ "convert-source-map": "^1.6.0"
+ }
+ },
+ "validate-npm-package-name": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz",
+ "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=",
+ "dev": true,
+ "requires": {
+ "builtins": "^1.0.3"
+ }
+ },
+ "verror": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "core-util-is": "1.0.2",
+ "extsprintf": "^1.2.0"
+ },
+ "dependencies": {
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+ "dev": true
+ }
+ }
+ },
+ "walker": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
+ "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
+ "dev": true,
+ "requires": {
+ "makeerror": "1.0.12"
+ }
+ },
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "wide-align": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
+ "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
+ "dev": true,
+ "requires": {
+ "string-width": "^1.0.2 || 2 || 3 || 4"
+ }
+ },
+ "widest-line": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz",
+ "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==",
+ "dev": true,
+ "requires": {
+ "string-width": "^4.0.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+ "dev": true
+ },
+ "write-file-atomic": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz",
+ "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==",
+ "dev": true,
+ "requires": {
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.7"
+ }
+ },
+ "y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "yargs": {
+ "version": "17.6.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.0.tgz",
+ "integrity": "sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==",
+ "dev": true,
+ "requires": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.0.0"
+ }
+ },
+ "yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "dev": true
+ },
+ "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
+ }
+ }
+}
diff --git a/typescript/rapier-compat/package.json b/typescript/rapier-compat/package.json
new file mode 100644
index 000000000..f97e9cf4c
--- /dev/null
+++ b/typescript/rapier-compat/package.json
@@ -0,0 +1,59 @@
+{
+ "name": "build-rapier",
+ "description": "Build scripts for compatibility package with inlined webassembly as base64.",
+ "private": true,
+ "scripts": {
+ "build-rust-2d-non-deterministic": "./build-rust.sh -f non-deterministic -d 2",
+ "build-rust-2d-deterministic": "./build-rust.sh -f deterministic -d 2",
+ "build-rust-2d-simd": "./build-rust.sh -f simd -d 2",
+ "build-rust-2d-all": "npm run build-rust-2d-non-deterministic && npm run build-rust-2d-deterministic && npm run build-rust-2d-simd",
+ "build-rust-3d-non-deterministic": "./build-rust.sh -f non-deterministic -d 3",
+ "build-rust-3d-deterministic": "./build-rust.sh -f deterministic -d 3",
+ "build-rust-3d-simd": "./build-rust.sh -f simd -d 3",
+ "build-rust-3d-all": "npm run build-rust-3d-non-deterministic && npm run build-rust-3d-deterministic && npm run build-rust-3d-simd",
+ "build-rust-all": "npm run build-rust-2d-all && npm run build-rust-3d-all",
+ "build-genjs": "sh ./gen_src.sh",
+ "build-js": "rollup --config rollup.config.js --bundleConfigAsCjs",
+ "fix-raw-file": "sh ./fix_raw_file.sh",
+ "build": "npm run clean && npm run build-rust-all && npm run build-genjs && npm run build-js && npm run fix-raw-file",
+ "clean": "rimraf gen2d gen3d builds",
+ "test": "jest --detectOpenHandles",
+ "all": "npm run build"
+ },
+ "dependencies": {
+ "base64-js": "^1.5.1"
+ },
+ "devDependencies": {
+ "@rollup/plugin-commonjs": "^23.0.2",
+ "@rollup/plugin-node-resolve": "^15.0.1",
+ "@rollup/plugin-typescript": "^9.0.2",
+ "@rollup/plugin-terser": "0.1.0",
+ "@types/jest": "^29.2.1",
+ "jest": "^29.2.2",
+ "rimraf": "^3.0.2",
+ "rollup": "^3.2.5",
+ "rollup-plugin-base64": "^1.0.1",
+ "rollup-plugin-copy": "^3.4.0",
+ "rollup-plugin-filesize": "^9.1.2",
+ "ts-jest": "^29.0.3",
+ "tslib": "^2.4.1",
+ "typescript": "^4.8.4"
+ },
+ "jest": {
+ "roots": [
+ "/tests"
+ ],
+ "preset": "ts-jest",
+ "collectCoverageFrom": [
+ "builds/**/pkg/**/*.js"
+ ],
+ "transformIgnorePatterns": [
+ "[/\\\\]node_modules[/\\\\].+\\.(js|ts)$",
+ "builds/.*/[/\\\\]pkg[/\\\\].+\\.(js|ts)$"
+ ],
+ "moduleFileExtensions": [
+ "ts",
+ "js"
+ ]
+ }
+}
diff --git a/typescript/rapier-compat/rollup.config.js b/typescript/rapier-compat/rollup.config.js
new file mode 100644
index 000000000..d127c6714
--- /dev/null
+++ b/typescript/rapier-compat/rollup.config.js
@@ -0,0 +1,85 @@
+import commonjs from "@rollup/plugin-commonjs";
+import {nodeResolve} from "@rollup/plugin-node-resolve";
+import typescript from "@rollup/plugin-typescript";
+import terser from "@rollup/plugin-terser";
+import path from "path";
+import {base64} from "rollup-plugin-base64";
+import copy from "rollup-plugin-copy";
+import filesize from "rollup-plugin-filesize";
+
+const config = (dim, features_postfix) => ({
+ input: `builds/${features_postfix}/gen${dim}/rapier.ts`,
+ output: [
+ {
+ file: `builds/${features_postfix}/pkg/rapier.mjs`,
+ format: "es",
+ sourcemap: true,
+ exports: "named",
+ },
+ {
+ file: `builds/${features_postfix}/pkg/rapier.cjs`,
+ format: "cjs",
+ sourcemap: true,
+ exports: "named",
+ },
+ ],
+ plugins: [
+ copy({
+ targets: [
+ {
+ src: `builds/${features_postfix}/wasm-build/package.json`,
+ dest: `builds/${features_postfix}/pkg/`,
+ transform(content) {
+ let config = JSON.parse(content.toString());
+ config.name = `@dimforge/rapier${features_postfix}-compat`;
+ config.description +=
+ " Compatibility package with inlined webassembly as base64.";
+ config.types = "rapier.d.ts";
+ config.main = "rapier.cjs";
+ config.module = "rapier.mjs";
+ config.exports = {
+ ".": {
+ types: "./rapier.d.ts",
+ require: "./rapier.cjs",
+ import: "./rapier.mjs",
+ },
+ };
+ // delete config.module;
+ config.files = ["*"];
+ return JSON.stringify(config, undefined, 2);
+ },
+ },
+ {
+ src: `../rapier${features_postfix}/LICENSE`,
+ dest: `builds/${features_postfix}/pkg`,
+ },
+ {
+ src: `../rapier${features_postfix}/README.md`,
+ dest: `builds/${features_postfix}/pkg`,
+ },
+ ],
+ }),
+ base64({include: "**/*.wasm"}),
+ terser(),
+ nodeResolve(),
+ commonjs(),
+ typescript({
+ tsconfig: path.resolve(
+ __dirname,
+ `builds/${features_postfix}/tsconfig.pkg.json`,
+ ),
+ sourceMap: true,
+ inlineSources: true,
+ }),
+ filesize(),
+ ],
+});
+
+export default [
+ config("2d", "2d"),
+ config("2d", "2d-deterministic"),
+ config("2d", "2d-simd"),
+ config("3d", "3d"),
+ config("3d", "3d-deterministic"),
+ config("3d", "3d-simd"),
+];
diff --git a/typescript/rapier-compat/src2d/init.ts b/typescript/rapier-compat/src2d/init.ts
new file mode 100644
index 000000000..668bfe130
--- /dev/null
+++ b/typescript/rapier-compat/src2d/init.ts
@@ -0,0 +1,12 @@
+// @ts-ignore
+import wasmBase64 from "../pkg/rapier_wasm2d_bg.wasm";
+import wasmInit from "../pkg/rapier_wasm2d";
+import base64 from "base64-js";
+
+/**
+ * Initializes RAPIER.
+ * Has to be called and awaited before using any library methods.
+ */
+export async function init() {
+ await wasmInit(base64.toByteArray(wasmBase64 as unknown as string).buffer);
+}
diff --git a/typescript/rapier-compat/src2d/raw.ts b/typescript/rapier-compat/src2d/raw.ts
new file mode 100644
index 000000000..4eadaffad
--- /dev/null
+++ b/typescript/rapier-compat/src2d/raw.ts
@@ -0,0 +1 @@
+export * from "../pkg/rapier_wasm2d";
diff --git a/typescript/rapier-compat/src3d/init.ts b/typescript/rapier-compat/src3d/init.ts
new file mode 100644
index 000000000..15b14ada1
--- /dev/null
+++ b/typescript/rapier-compat/src3d/init.ts
@@ -0,0 +1,12 @@
+// @ts-ignore
+import wasmBase64 from "../pkg/rapier_wasm3d_bg.wasm";
+import wasmInit from "../pkg/rapier_wasm3d";
+import base64 from "base64-js";
+
+/**
+ * Initializes RAPIER.
+ * Has to be called and awaited before using any library methods.
+ */
+export async function init() {
+ await wasmInit(base64.toByteArray(wasmBase64 as unknown as string).buffer);
+}
diff --git a/typescript/rapier-compat/src3d/raw.ts b/typescript/rapier-compat/src3d/raw.ts
new file mode 100644
index 000000000..b123ae6b3
--- /dev/null
+++ b/typescript/rapier-compat/src3d/raw.ts
@@ -0,0 +1 @@
+export * from "../pkg/rapier_wasm3d";
diff --git a/typescript/rapier-compat/tests/World2d.test.ts b/typescript/rapier-compat/tests/World2d.test.ts
new file mode 100644
index 000000000..45a3bb72f
--- /dev/null
+++ b/typescript/rapier-compat/tests/World2d.test.ts
@@ -0,0 +1,23 @@
+import {init, Vector2, World} from "../builds/2d-deterministic/pkg";
+
+describe("2d/World", () => {
+ let world: World;
+
+ beforeAll(init);
+
+ afterAll(async () => {
+ await Promise.resolve();
+ });
+
+ beforeEach(() => {
+ world = new World(new Vector2(0, 9.8));
+ });
+
+ afterEach(() => {
+ world.free();
+ });
+
+ test("constructor", () => {
+ expect(world.colliders.len()).toBe(0);
+ });
+});
diff --git a/typescript/rapier-compat/tests/World3d.test.ts b/typescript/rapier-compat/tests/World3d.test.ts
new file mode 100644
index 000000000..e0ddd5467
--- /dev/null
+++ b/typescript/rapier-compat/tests/World3d.test.ts
@@ -0,0 +1,23 @@
+import {init, Vector3, World} from "../builds/3d-deterministic/pkg";
+
+describe("3d/World", () => {
+ let world: World;
+
+ beforeAll(init);
+
+ afterAll(async () => {
+ await Promise.resolve();
+ });
+
+ beforeEach(() => {
+ world = new World(new Vector3(0, 9.8, 0));
+ });
+
+ afterEach(() => {
+ world.free();
+ });
+
+ test("constructor", () => {
+ expect(world.colliders.len()).toBe(0);
+ });
+});
diff --git a/typescript/rapier-compat/tests/math2d.test.ts b/typescript/rapier-compat/tests/math2d.test.ts
new file mode 100644
index 000000000..a75605650
--- /dev/null
+++ b/typescript/rapier-compat/tests/math2d.test.ts
@@ -0,0 +1,15 @@
+import {Vector2, VectorOps} from "../builds/2d-deterministic/pkg";
+
+describe("2d/math", () => {
+ test("Vector2", () => {
+ const v = new Vector2(0, 1);
+ expect(v.x).toBe(0);
+ expect(v.y).toBe(1);
+ });
+
+ test("VectorOps", () => {
+ const v = VectorOps.new(0, 1);
+ expect(v.x).toBe(0);
+ expect(v.y).toBe(1);
+ });
+});
diff --git a/typescript/rapier-compat/tests/math3d.test.ts b/typescript/rapier-compat/tests/math3d.test.ts
new file mode 100644
index 000000000..2ff194cc6
--- /dev/null
+++ b/typescript/rapier-compat/tests/math3d.test.ts
@@ -0,0 +1,17 @@
+import {Vector3, VectorOps} from "../builds/3d-deterministic/pkg";
+
+describe("3d/math", () => {
+ test("Vector3", () => {
+ const v = new Vector3(0, 1, 2);
+ expect(v.x).toBe(0);
+ expect(v.y).toBe(1);
+ expect(v.z).toBe(2);
+ });
+
+ test("VectorOps", () => {
+ const v = VectorOps.new(0, 1, 2);
+ expect(v.x).toBe(0);
+ expect(v.y).toBe(1);
+ expect(v.z).toBe(2);
+ });
+});
diff --git a/typescript/rapier-compat/tsconfig.common.json b/typescript/rapier-compat/tsconfig.common.json
new file mode 100644
index 000000000..37bd7d7f6
--- /dev/null
+++ b/typescript/rapier-compat/tsconfig.common.json
@@ -0,0 +1,15 @@
+{
+ "compilerOptions": {
+ "module": "ES6",
+ "target": "es6",
+ "noEmitOnError": true,
+ "noImplicitAny": true,
+ "noImplicitThis": true,
+ "strictFunctionTypes": true,
+ "lib": ["es6", "DOM"],
+ "moduleResolution": "node",
+ "esModuleInterop": true,
+ "sourceMap": true,
+ "declaration": true
+ }
+}
diff --git a/typescript/rapier-compat/tsconfig.json b/typescript/rapier-compat/tsconfig.json
new file mode 100644
index 000000000..beeca9441
--- /dev/null
+++ b/typescript/rapier-compat/tsconfig.json
@@ -0,0 +1,10 @@
+{
+ "extends": "./tsconfig.common.json",
+ "compilerOptions": {
+ "lib": ["es6", "DOM"],
+ "esModuleInterop": true,
+ "types": ["jest"],
+ "outDir": "./dist"
+ },
+ "include": ["./tests/**/*.test.ts"]
+}
diff --git a/typescript/rapier-compat/tsconfig.pkg2d.json b/typescript/rapier-compat/tsconfig.pkg2d.json
new file mode 100644
index 000000000..77349ed25
--- /dev/null
+++ b/typescript/rapier-compat/tsconfig.pkg2d.json
@@ -0,0 +1,8 @@
+{
+ "extends": "./tsconfig.common.json",
+ "compilerOptions": {
+ "rootDir": "./gen2d",
+ "outDir": "./2d"
+ },
+ "files": ["./gen2d/rapier.ts"]
+}
diff --git a/typescript/rapier-compat/tsconfig.pkg3d.json b/typescript/rapier-compat/tsconfig.pkg3d.json
new file mode 100644
index 000000000..3d7323e88
--- /dev/null
+++ b/typescript/rapier-compat/tsconfig.pkg3d.json
@@ -0,0 +1,8 @@
+{
+ "extends": "./tsconfig.common.json",
+ "compilerOptions": {
+ "rootDir": "./gen3d",
+ "outDir": "."
+ },
+ "files": ["./gen3d/rapier.ts"]
+}
diff --git a/typescript/src.ts/coarena.ts b/typescript/src.ts/coarena.ts
new file mode 100644
index 000000000..9bf978a54
--- /dev/null
+++ b/typescript/src.ts/coarena.ts
@@ -0,0 +1,70 @@
+export class Coarena {
+ fconv: Float64Array;
+ uconv: Uint32Array;
+ data: Array;
+ size: number;
+
+ public constructor() {
+ this.fconv = new Float64Array(1);
+ this.uconv = new Uint32Array(this.fconv.buffer);
+ this.data = new Array();
+ this.size = 0;
+ }
+
+ public set(handle: number, data: T) {
+ let i = this.index(handle);
+ while (this.data.length <= i) {
+ this.data.push(null);
+ }
+
+ if (this.data[i] == null) this.size += 1;
+ this.data[i] = data;
+ }
+
+ public len(): number {
+ return this.size;
+ }
+
+ public delete(handle: number) {
+ let i = this.index(handle);
+ if (i < this.data.length) {
+ if (this.data[i] != null) this.size -= 1;
+ this.data[i] = null;
+ }
+ }
+
+ public clear() {
+ this.data = new Array();
+ }
+
+ public get(handle: number): T | null {
+ let i = this.index(handle);
+ if (i < this.data.length) {
+ return this.data[i];
+ } else {
+ return null;
+ }
+ }
+
+ public forEach(f: (elt: T) => void) {
+ for (const elt of this.data) {
+ if (elt != null) f(elt);
+ }
+ }
+
+ public getAll(): Array {
+ return this.data.filter((elt) => elt != null);
+ }
+
+ private index(handle: number): number {
+ /// Extracts the index part of a handle (the lower 32 bits).
+ /// This is done by first injecting the handle into an Float64Array
+ /// which is itself injected into an Uint32Array (at construction time).
+ /// The 0-th value of the Uint32Array will become the `number` integer
+ /// representation of the lower 32 bits.
+ /// Also `this.uconv[1]` then contains the generation number as a `number`,
+ /// which we don’t really need.
+ this.fconv[0] = handle;
+ return this.uconv[0];
+ }
+}
diff --git a/typescript/src.ts/control/character_controller.ts b/typescript/src.ts/control/character_controller.ts
new file mode 100644
index 000000000..4c10f82c2
--- /dev/null
+++ b/typescript/src.ts/control/character_controller.ts
@@ -0,0 +1,395 @@
+import {RawKinematicCharacterController, RawCharacterCollision} from "../raw";
+import {Rotation, Vector, VectorOps, scratchBuffer} from "../math";
+import {
+ BroadPhase,
+ Collider,
+ ColliderSet,
+ InteractionGroups,
+ NarrowPhase,
+ Shape,
+} from "../geometry";
+import {QueryFilterFlags, World} from "../pipeline";
+import {IntegrationParameters, RigidBody, RigidBodySet} from "../dynamics";
+
+/**
+ * A collision between the character and an obstacle hit on its path.
+ */
+export class CharacterCollision {
+ /** The collider involved in the collision. Null if the collider no longer exists in the physics world. */
+ public collider: Collider | null;
+ /** The translation delta applied to the character before this collision took place. */
+ public translationDeltaApplied: Vector;
+ /** The translation delta the character would move after this collision if there is no other obstacles. */
+ public translationDeltaRemaining: Vector;
+ /** The time-of-impact between the character and the obstacles. */
+ public toi: number;
+ /** The world-space contact point on the collider when the collision happens. */
+ public witness1: Vector;
+ /** The local-space contact point on the character when the collision happens. */
+ public witness2: Vector;
+ /** The world-space outward contact normal on the collider when the collision happens. */
+ public normal1: Vector;
+ /** The local-space outward contact normal on the character when the collision happens. */
+ public normal2: Vector;
+}
+
+/**
+ * A character controller for controlling kinematic bodies and parentless colliders by hitting
+ * and sliding against obstacles.
+ */
+export class KinematicCharacterController {
+ private raw: RawKinematicCharacterController;
+ private rawCharacterCollision: RawCharacterCollision;
+
+ private params: IntegrationParameters;
+ private broadPhase: BroadPhase;
+ private narrowPhase: NarrowPhase;
+ private bodies: RigidBodySet;
+ private colliders: ColliderSet;
+ private _applyImpulsesToDynamicBodies: boolean;
+ private _characterMass: number | null;
+
+ constructor(
+ offset: number,
+ params: IntegrationParameters,
+ broadPhase: BroadPhase,
+ narrowPhase: NarrowPhase,
+ bodies: RigidBodySet,
+ colliders: ColliderSet,
+ ) {
+ this.params = params;
+ this.bodies = bodies;
+ this.colliders = colliders;
+ this.broadPhase = broadPhase;
+ this.narrowPhase = narrowPhase;
+ this.raw = new RawKinematicCharacterController(offset);
+ this.rawCharacterCollision = new RawCharacterCollision();
+ this._applyImpulsesToDynamicBodies = false;
+ this._characterMass = null;
+ }
+
+ /** @internal */
+ public free() {
+ if (!!this.raw) {
+ this.raw.free();
+ this.rawCharacterCollision.free();
+ }
+
+ this.raw = undefined;
+ this.rawCharacterCollision = undefined;
+ }
+
+ /**
+ * The direction that goes "up". Used to determine where the floor is, and the floor’s angle.
+ */
+ public up(): Vector {
+ return this.raw.up();
+ }
+
+ /**
+ * Sets the direction that goes "up". Used to determine where the floor is, and the floor’s angle.
+ */
+ public setUp(vector: Vector) {
+ let rawVect = VectorOps.intoRaw(vector);
+ return this.raw.setUp(rawVect);
+ rawVect.free();
+ }
+
+ public applyImpulsesToDynamicBodies(): boolean {
+ return this._applyImpulsesToDynamicBodies;
+ }
+
+ public setApplyImpulsesToDynamicBodies(enabled: boolean) {
+ this._applyImpulsesToDynamicBodies = enabled;
+ }
+
+ /**
+ * Returns the custom value of the character mass, if it was set by `this.setCharacterMass`.
+ */
+ public characterMass(): number | null {
+ return this._characterMass;
+ }
+
+ /**
+ * Set the mass of the character to be used for impulse resolution if `self.applyImpulsesToDynamicBodies`
+ * is set to `true`.
+ *
+ * If no character mass is set explicitly (or if it is set to `null`) it is automatically assumed to be equal
+ * to the mass of the rigid-body the character collider is attached to; or equal to 0 if the character collider
+ * isn’t attached to any rigid-body.
+ *
+ * @param mass - The mass to set.
+ */
+ public setCharacterMass(mass: number | null) {
+ this._characterMass = mass;
+ }
+
+ /**
+ * A small gap to preserve between the character and its surroundings.
+ *
+ * This value should not be too large to avoid visual artifacts, but shouldn’t be too small
+ * (must not be zero) to improve numerical stability of the character controller.
+ */
+ public offset(): number {
+ return this.raw.offset();
+ }
+
+ /**
+ * Sets a small gap to preserve between the character and its surroundings.
+ *
+ * This value should not be too large to avoid visual artifacts, but shouldn’t be too small
+ * (must not be zero) to improve numerical stability of the character controller.
+ */
+ public setOffset(value: number) {
+ this.raw.setOffset(value);
+ }
+
+ /// Increase this number if your character appears to get stuck when sliding against surfaces.
+ ///
+ /// This is a small distance applied to the movement toward the contact normals of shapes hit
+ /// by the character controller. This helps shape-casting not getting stuck in an always-penetrating
+ /// state during the sliding calculation.
+ ///
+ /// This value should remain fairly small since it can introduce artificial "bumps" when sliding
+ /// along a flat surface.
+ public normalNudgeFactor(): number {
+ return this.raw.normalNudgeFactor();
+ }
+
+ /// Increase this number if your character appears to get stuck when sliding against surfaces.
+ ///
+ /// This is a small distance applied to the movement toward the contact normals of shapes hit
+ /// by the character controller. This helps shape-casting not getting stuck in an always-penetrating
+ /// state during the sliding calculation.
+ ///
+ /// This value should remain fairly small since it can introduce artificial "bumps" when sliding
+ /// along a flat surface.
+ public setNormalNudgeFactor(value: number) {
+ this.raw.setNormalNudgeFactor(value);
+ }
+
+ /**
+ * Is sliding against obstacles enabled?
+ */
+ public slideEnabled(): boolean {
+ return this.raw.slideEnabled();
+ }
+
+ /**
+ * Enable or disable sliding against obstacles.
+ */
+ public setSlideEnabled(enabled: boolean) {
+ this.raw.setSlideEnabled(enabled);
+ }
+
+ /**
+ * The maximum step height a character can automatically step over.
+ */
+ public autostepMaxHeight(): number | null {
+ return this.raw.autostepMaxHeight();
+ }
+
+ /**
+ * The minimum width of free space that must be available after stepping on a stair.
+ */
+ public autostepMinWidth(): number | null {
+ return this.raw.autostepMinWidth();
+ }
+
+ /**
+ * Can the character automatically step over dynamic bodies too?
+ */
+ public autostepIncludesDynamicBodies(): boolean | null {
+ return this.raw.autostepIncludesDynamicBodies();
+ }
+
+ /**
+ * Is automatically stepping over small objects enabled?
+ */
+ public autostepEnabled(): boolean {
+ return this.raw.autostepEnabled();
+ }
+
+ /**
+ * Enabled automatically stepping over small objects.
+ *
+ * @param maxHeight - The maximum step height a character can automatically step over.
+ * @param minWidth - The minimum width of free space that must be available after stepping on a stair.
+ * @param includeDynamicBodies - Can the character automatically step over dynamic bodies too?
+ */
+ public enableAutostep(
+ maxHeight: number,
+ minWidth: number,
+ includeDynamicBodies: boolean,
+ ) {
+ this.raw.enableAutostep(maxHeight, minWidth, includeDynamicBodies);
+ }
+
+ /**
+ * Disable automatically stepping over small objects.
+ */
+ public disableAutostep() {
+ return this.raw.disableAutostep();
+ }
+
+ /**
+ * The maximum angle (radians) between the floor’s normal and the `up` vector that the
+ * character is able to climb.
+ */
+ public maxSlopeClimbAngle(): number {
+ return this.raw.maxSlopeClimbAngle();
+ }
+
+ /**
+ * Sets the maximum angle (radians) between the floor’s normal and the `up` vector that the
+ * character is able to climb.
+ */
+ public setMaxSlopeClimbAngle(angle: number) {
+ this.raw.setMaxSlopeClimbAngle(angle);
+ }
+
+ /**
+ * The minimum angle (radians) between the floor’s normal and the `up` vector before the
+ * character starts to slide down automatically.
+ */
+ public minSlopeSlideAngle(): number {
+ return this.raw.minSlopeSlideAngle();
+ }
+
+ /**
+ * Sets the minimum angle (radians) between the floor’s normal and the `up` vector before the
+ * character starts to slide down automatically.
+ */
+ public setMinSlopeSlideAngle(angle: number) {
+ this.raw.setMinSlopeSlideAngle(angle);
+ }
+
+ /**
+ * If snap-to-ground is enabled, should the character be automatically snapped to the ground if
+ * the distance between the ground and its feet are smaller than the specified threshold?
+ */
+ public snapToGroundDistance(): number | null {
+ return this.raw.snapToGroundDistance();
+ }
+
+ /**
+ * Enables automatically snapping the character to the ground if the distance between
+ * the ground and its feet are smaller than the specified threshold.
+ */
+ public enableSnapToGround(distance: number) {
+ this.raw.enableSnapToGround(distance);
+ }
+
+ /**
+ * Disables automatically snapping the character to the ground.
+ */
+ public disableSnapToGround() {
+ this.raw.disableSnapToGround();
+ }
+
+ /**
+ * Is automatically snapping the character to the ground enabled?
+ */
+ public snapToGroundEnabled(): boolean {
+ return this.raw.snapToGroundEnabled();
+ }
+
+ /**
+ * Computes the movement the given collider is able to execute after hitting and sliding on obstacles.
+ *
+ * @param collider - The collider to move.
+ * @param desiredTranslationDelta - The desired collider movement.
+ * @param filterFlags - Flags for excluding whole subsets of colliders from the obstacles taken into account.
+ * @param filterGroups - Groups for excluding colliders with incompatible collision groups from the obstacles
+ * taken into account.
+ * @param filterPredicate - Any collider for which this closure returns `false` will be excluded from the
+ * obstacles taken into account.
+ */
+ public computeColliderMovement(
+ collider: Collider,
+ desiredTranslationDelta: Vector,
+ filterFlags?: QueryFilterFlags,
+ filterGroups?: InteractionGroups,
+ filterPredicate?: (collider: Collider) => boolean,
+ ) {
+ let rawTranslationDelta = VectorOps.intoRaw(desiredTranslationDelta);
+ this.raw.computeColliderMovement(
+ this.params.dt,
+ this.broadPhase.raw,
+ this.narrowPhase.raw,
+ this.bodies.raw,
+ this.colliders.raw,
+ collider.handle,
+ rawTranslationDelta,
+ this._applyImpulsesToDynamicBodies,
+ this._characterMass,
+ filterFlags,
+ filterGroups,
+ this.colliders.castClosure(filterPredicate),
+ );
+ rawTranslationDelta.free();
+ }
+
+ /**
+ * The movement computed by the last call to `this.computeColliderMovement`.
+ */
+ public computedMovement(target?: Vector): Vector {
+ this.raw.computedMovement(scratchBuffer);
+ return VectorOps.fromBuffer(scratchBuffer, target);
+ }
+
+ /**
+ * The result of ground detection computed by the last call to `this.computeColliderMovement`.
+ */
+ public computedGrounded(): boolean {
+ return this.raw.computedGrounded();
+ }
+
+ /**
+ * The number of collisions against obstacles detected along the path of the last call
+ * to `this.computeColliderMovement`.
+ */
+ public numComputedCollisions(): number {
+ return this.raw.numComputedCollisions();
+ }
+
+ /**
+ * Returns the collision against one of the obstacles detected along the path of the last
+ * call to `this.computeColliderMovement`.
+ *
+ * @param i - The i-th collision will be returned.
+ * @param out - If this argument is set, it will be filled with the collision information.
+ */
+ public computedCollision(
+ i: number,
+ out?: CharacterCollision,
+ ): CharacterCollision | null {
+ if (!this.raw.computedCollision(i, this.rawCharacterCollision)) {
+ return null;
+ } else {
+ let c = this.rawCharacterCollision;
+ out = out ?? new CharacterCollision();
+ c.translationDeltaApplied(scratchBuffer);
+ out.translationDeltaApplied = VectorOps.fromBuffer(
+ scratchBuffer,
+ out.translationDeltaApplied,
+ );
+ c.translationDeltaRemaining(scratchBuffer);
+ out.translationDeltaRemaining = VectorOps.fromBuffer(
+ scratchBuffer,
+ out.translationDeltaRemaining,
+ );
+ out.toi = c.toi();
+ c.worldWitness1(scratchBuffer);
+ out.witness1 = VectorOps.fromBuffer(scratchBuffer, out.witness1);
+ c.worldWitness2(scratchBuffer);
+ out.witness2 = VectorOps.fromBuffer(scratchBuffer, out.witness2);
+ c.worldNormal1(scratchBuffer);
+ out.normal1 = VectorOps.fromBuffer(scratchBuffer, out.normal1);
+ c.worldNormal2(scratchBuffer);
+ out.normal2 = VectorOps.fromBuffer(scratchBuffer, out.normal2);
+ out.collider = this.colliders.get(c.handle());
+ return out;
+ }
+ }
+}
diff --git a/typescript/src.ts/control/index.ts b/typescript/src.ts/control/index.ts
new file mode 100644
index 000000000..43e495a56
--- /dev/null
+++ b/typescript/src.ts/control/index.ts
@@ -0,0 +1,6 @@
+export * from "./character_controller";
+export * from "./pid_controller";
+
+// #if DIM3
+export * from "./ray_cast_vehicle_controller";
+// #endif
diff --git a/typescript/src.ts/control/pid_controller.ts b/typescript/src.ts/control/pid_controller.ts
new file mode 100644
index 000000000..a8f9bdac1
--- /dev/null
+++ b/typescript/src.ts/control/pid_controller.ts
@@ -0,0 +1,211 @@
+import {RawPidController} from "../raw";
+import {Rotation, RotationOps, scratchBuffer, Vector, VectorOps} from "../math";
+import {Collider, ColliderSet, InteractionGroups, Shape} from "../geometry";
+import {QueryFilterFlags, World} from "../pipeline";
+import {IntegrationParameters, RigidBody, RigidBodySet} from "../dynamics";
+
+// TODO: unify with the JointAxesMask
+/**
+ * An enum representing the possible joint axes controlled by a PidController.
+ * They can be ORed together, like:
+ * PidAxesMask.LinX || PidAxesMask.LinY
+ * to get a pid controller that only constraints the translational X and Y axes.
+ *
+ * Possible axes are:
+ *
+ * - `X`: X translation axis
+ * - `Y`: Y translation axis
+ * - `Z`: Z translation axis
+ * - `AngX`: X angular rotation axis (3D only)
+ * - `AngY`: Y angular rotation axis (3D only)
+ * - `AngZ`: Z angular rotation axis
+ */
+export enum PidAxesMask {
+ None = 0,
+ LinX = 1 << 0,
+ LinY = 1 << 1,
+ LinZ = 1 << 2,
+ // #if DIM3
+ AngX = 1 << 3,
+ AngY = 1 << 4,
+ // #endif
+ AngZ = 1 << 5,
+ // #if DIM2
+ AllLin = PidAxesMask.LinX | PidAxesMask.LinY,
+ AllAng = PidAxesMask.AngZ,
+ // #endif
+ // #if DIM3
+ AllLin = PidAxesMask.LinX | PidAxesMask.LinY | PidAxesMask.LinZ,
+ AllAng = PidAxesMask.AngX | PidAxesMask.AngY | PidAxesMask.AngZ,
+ // #endif
+ All = PidAxesMask.AllLin | PidAxesMask.AllAng,
+}
+
+/**
+ * A controller for controlling dynamic bodies using the
+ * Proportional-Integral-Derivative correction model.
+ */
+export class PidController {
+ private raw: RawPidController;
+
+ private params: IntegrationParameters;
+ private bodies: RigidBodySet;
+
+ constructor(
+ params: IntegrationParameters,
+ bodies: RigidBodySet,
+ kp: number,
+ ki: number,
+ kd: number,
+ axes: PidAxesMask,
+ ) {
+ this.params = params;
+ this.bodies = bodies;
+ this.raw = new RawPidController(kp, ki, kd, axes);
+ }
+
+ /** @internal */
+ public free() {
+ if (!!this.raw) {
+ this.raw.free();
+ }
+
+ this.raw = undefined;
+ }
+
+ public setKp(kp: number, axes: PidAxesMask) {
+ this.raw.set_kp(kp, axes);
+ }
+
+ public setKi(ki: number, axes: PidAxesMask) {
+ this.raw.set_kp(ki, axes);
+ }
+
+ public setKd(kd: number, axes: PidAxesMask) {
+ this.raw.set_kp(kd, axes);
+ }
+
+ public setAxes(axes: PidAxesMask) {
+ this.raw.set_axes_mask(axes);
+ }
+
+ public resetIntegrals() {
+ this.raw.reset_integrals();
+ }
+
+ public applyLinearCorrection(
+ body: RigidBody,
+ targetPosition: Vector,
+ targetLinvel: Vector,
+ ) {
+ let rawPos = VectorOps.intoRaw(targetPosition);
+ let rawVel = VectorOps.intoRaw(targetLinvel);
+ this.raw.apply_linear_correction(
+ this.params.dt,
+ this.bodies.raw,
+ body.handle,
+ rawPos,
+ rawVel,
+ );
+ rawPos.free();
+ rawVel.free();
+ }
+
+ // #if DIM2
+ public applyAngularCorrection(
+ body: RigidBody,
+ targetRotation: number,
+ targetAngVel: number,
+ ) {
+ this.raw.apply_angular_correction(
+ this.params.dt,
+ this.bodies.raw,
+ body.handle,
+ targetRotation,
+ targetAngVel,
+ );
+ }
+ // #endif
+
+ // #if DIM3
+ public applyAngularCorrection(
+ body: RigidBody,
+ targetRotation: Rotation,
+ targetAngVel: Vector,
+ ) {
+ let rawPos = RotationOps.intoRaw(targetRotation);
+ let rawVel = VectorOps.intoRaw(targetAngVel);
+ this.raw.apply_angular_correction(
+ this.params.dt,
+ this.bodies.raw,
+ body.handle,
+ rawPos,
+ rawVel,
+ );
+ rawPos.free();
+ rawVel.free();
+ }
+ // #endif
+
+ public linearCorrection(
+ body: RigidBody,
+ targetPosition: Vector,
+ targetLinvel: Vector,
+ target?: Vector,
+ ): Vector {
+ let rawPos = VectorOps.intoRaw(targetPosition);
+ let rawVel = VectorOps.intoRaw(targetLinvel);
+ this.raw.linear_correction(
+ this.params.dt,
+ this.bodies.raw,
+ body.handle,
+ rawPos,
+ rawVel,
+ scratchBuffer,
+ );
+ rawPos.free();
+ rawVel.free();
+
+ return VectorOps.fromBuffer(scratchBuffer, target);
+ }
+
+ // #if DIM2
+ public angularCorrection(
+ body: RigidBody,
+ targetRotation: number,
+ targetAngVel: number,
+ ): number {
+ return this.raw.angular_correction(
+ this.params.dt,
+ this.bodies.raw,
+ body.handle,
+ targetRotation,
+ targetAngVel,
+ );
+ }
+ // #endif
+
+ // #if DIM3
+ public angularCorrection(
+ body: RigidBody,
+ targetRotation: Rotation,
+ targetAngVel: Vector,
+ target?: Vector,
+ ): Vector {
+ let rawPos = RotationOps.intoRaw(targetRotation);
+ let rawVel = VectorOps.intoRaw(targetAngVel);
+ this.raw.angular_correction(
+ this.params.dt,
+ this.bodies.raw,
+ body.handle,
+ rawPos,
+ rawVel,
+ scratchBuffer,
+ );
+ rawPos.free();
+ rawVel.free();
+
+ return VectorOps.fromBuffer(scratchBuffer, target);
+ }
+ // #endif
+}
diff --git a/typescript/src.ts/control/ray_cast_vehicle_controller.ts b/typescript/src.ts/control/ray_cast_vehicle_controller.ts
new file mode 100644
index 000000000..55e4b52ff
--- /dev/null
+++ b/typescript/src.ts/control/ray_cast_vehicle_controller.ts
@@ -0,0 +1,518 @@
+import {RawDynamicRayCastVehicleController} from "../raw";
+import {scratchBuffer, Vector, VectorOps} from "../math";
+import {
+ BroadPhase,
+ Collider,
+ ColliderSet,
+ InteractionGroups,
+ NarrowPhase,
+} from "../geometry";
+import {QueryFilterFlags} from "../pipeline";
+import {RigidBody, RigidBodyHandle, RigidBodySet} from "../dynamics";
+
+/**
+ * A character controller to simulate vehicles using ray-casting for the wheels.
+ */
+export class DynamicRayCastVehicleController {
+ private raw: RawDynamicRayCastVehicleController;
+ private broadPhase: BroadPhase;
+ private narrowPhase: NarrowPhase;
+ private bodies: RigidBodySet;
+ private colliders: ColliderSet;
+ private _chassis: RigidBody;
+
+ constructor(
+ chassis: RigidBody,
+ broadPhase: BroadPhase,
+ narrowPhase: NarrowPhase,
+ bodies: RigidBodySet,
+ colliders: ColliderSet,
+ ) {
+ this.raw = new RawDynamicRayCastVehicleController(chassis.handle);
+ this.broadPhase = broadPhase;
+ this.narrowPhase = narrowPhase;
+ this.bodies = bodies;
+ this.colliders = colliders;
+ this._chassis = chassis;
+ }
+
+ /** @internal */
+ public free() {
+ if (!!this.raw) {
+ this.raw.free();
+ }
+
+ this.raw = undefined;
+ }
+
+ /**
+ * Updates the vehicle’s velocity based on its suspension, engine force, and brake.
+ *
+ * This directly updates the velocity of its chassis rigid-body.
+ *
+ * @param dt - Time increment used to integrate forces.
+ * @param filterFlags - Flag to exclude categories of objects from the wheels’ ray-cast.
+ * @param filterGroups - Only colliders compatible with these groups will be hit by the wheels’ ray-casts.
+ * @param filterPredicate - Callback to filter out which collider will be hit by the wheels’ ray-casts.
+ */
+ public updateVehicle(
+ dt: number,
+ filterFlags?: QueryFilterFlags,
+ filterGroups?: InteractionGroups,
+ filterPredicate?: (collider: Collider) => boolean,
+ ) {
+ this.raw.update_vehicle(
+ dt,
+ this.broadPhase.raw,
+ this.narrowPhase.raw,
+ this.bodies.raw,
+ this.colliders.raw,
+ filterFlags,
+ filterGroups,
+ this.colliders.castClosure(filterPredicate),
+ );
+ }
+
+ /**
+ * The current forward speed of the vehicle.
+ */
+ public currentVehicleSpeed(): number {
+ return this.raw.current_vehicle_speed();
+ }
+
+ /**
+ * The rigid-body used as the chassis.
+ */
+ public chassis(): RigidBody {
+ return this._chassis;
+ }
+
+ /**
+ * The chassis’ local _up_ direction (`0 = x, 1 = y, 2 = z`).
+ */
+ get indexUpAxis(): number {
+ return this.raw.index_up_axis();
+ }
+
+ /**
+ * Sets the chassis’ local _up_ direction (`0 = x, 1 = y, 2 = z`).
+ */
+ set indexUpAxis(axis: number) {
+ this.raw.set_index_up_axis(axis);
+ }
+
+ /**
+ * The chassis’ local _forward_ direction (`0 = x, 1 = y, 2 = z`).
+ */
+ get indexForwardAxis(): number {
+ return this.raw.index_forward_axis();
+ }
+
+ /**
+ * Sets the chassis’ local _forward_ direction (`0 = x, 1 = y, 2 = z`).
+ */
+ set setIndexForwardAxis(axis: number) {
+ this.raw.set_index_forward_axis(axis);
+ }
+
+ /**
+ * Adds a new wheel attached to this vehicle.
+ * @param chassisConnectionCs - The position of the wheel relative to the chassis.
+ * @param directionCs - The direction of the wheel’s suspension, relative to the chassis. The ray-casting will
+ * happen following this direction to detect the ground.
+ * @param axleCs - The wheel’s axle axis, relative to the chassis.
+ * @param suspensionRestLength - The rest length of the wheel’s suspension spring.
+ * @param radius - The wheel’s radius.
+ */
+ public addWheel(
+ chassisConnectionCs: Vector,
+ directionCs: Vector,
+ axleCs: Vector,
+ suspensionRestLength: number,
+ radius: number,
+ ) {
+ let rawChassisConnectionCs = VectorOps.intoRaw(chassisConnectionCs);
+ let rawDirectionCs = VectorOps.intoRaw(directionCs);
+ let rawAxleCs = VectorOps.intoRaw(axleCs);
+
+ this.raw.add_wheel(
+ rawChassisConnectionCs,
+ rawDirectionCs,
+ rawAxleCs,
+ suspensionRestLength,
+ radius,
+ );
+
+ rawChassisConnectionCs.free();
+ rawDirectionCs.free();
+ rawAxleCs.free();
+ }
+
+ /**
+ * The number of wheels attached to this vehicle.
+ */
+ public numWheels(): number {
+ return this.raw.num_wheels();
+ }
+
+ /*
+ *
+ * Access to wheel properties.
+ *
+ */
+ /*
+ * Getters + setters
+ */
+
+ /**
+ * The position of the i-th wheel, relative to the chassis.
+ *
+ * @param {number} i
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public wheelChassisConnectionPointCs(
+ i: number,
+ target?: Vector,
+ ): Vector | null {
+ const exists = this.raw.wheel_chassis_connection_point_cs(
+ i,
+ scratchBuffer,
+ );
+ return exists ? VectorOps.fromBuffer(scratchBuffer, target) : null;
+ }
+
+ /**
+ * Sets the position of the i-th wheel, relative to the chassis.
+ */
+ public setWheelChassisConnectionPointCs(i: number, value: Vector) {
+ let rawValue = VectorOps.intoRaw(value);
+ this.raw.set_wheel_chassis_connection_point_cs(i, rawValue);
+ rawValue.free();
+ }
+
+ /**
+ * The rest length of the i-th wheel’s suspension spring.
+ */
+ public wheelSuspensionRestLength(i: number): number | null {
+ return this.raw.wheel_suspension_rest_length(i);
+ }
+
+ /**
+ * Sets the rest length of the i-th wheel’s suspension spring.
+ */
+ public setWheelSuspensionRestLength(i: number, value: number) {
+ this.raw.set_wheel_suspension_rest_length(i, value);
+ }
+
+ /**
+ * The maximum distance the i-th wheel suspension can travel before and after its resting length.
+ */
+ public wheelMaxSuspensionTravel(i: number): number | null {
+ return this.raw.wheel_max_suspension_travel(i);
+ }
+
+ /**
+ * Sets the maximum distance the i-th wheel suspension can travel before and after its resting length.
+ */
+ public setWheelMaxSuspensionTravel(i: number, value: number) {
+ this.raw.set_wheel_max_suspension_travel(i, value);
+ }
+
+ /**
+ * The i-th wheel’s radius.
+ */
+ public wheelRadius(i: number): number | null {
+ return this.raw.wheel_radius(i);
+ }
+
+ /**
+ * Sets the i-th wheel’s radius.
+ */
+ public setWheelRadius(i: number, value: number) {
+ this.raw.set_wheel_radius(i, value);
+ }
+
+ /**
+ * The i-th wheel’s suspension stiffness.
+ *
+ * Increase this value if the suspension appears to not push the vehicle strong enough.
+ */
+ public wheelSuspensionStiffness(i: number): number | null {
+ return this.raw.wheel_suspension_stiffness(i);
+ }
+
+ /**
+ * Sets the i-th wheel’s suspension stiffness.
+ *
+ * Increase this value if the suspension appears to not push the vehicle strong enough.
+ */
+ public setWheelSuspensionStiffness(i: number, value: number) {
+ this.raw.set_wheel_suspension_stiffness(i, value);
+ }
+
+ /**
+ * The i-th wheel’s suspension’s damping when it is being compressed.
+ */
+ public wheelSuspensionCompression(i: number): number | null {
+ return this.raw.wheel_suspension_compression(i);
+ }
+
+ /**
+ * The i-th wheel’s suspension’s damping when it is being compressed.
+ */
+ public setWheelSuspensionCompression(i: number, value: number) {
+ this.raw.set_wheel_suspension_compression(i, value);
+ }
+
+ /**
+ * The i-th wheel’s suspension’s damping when it is being released.
+ *
+ * Increase this value if the suspension appears to overshoot.
+ */
+ public wheelSuspensionRelaxation(i: number): number | null {
+ return this.raw.wheel_suspension_relaxation(i);
+ }
+
+ /**
+ * Sets the i-th wheel’s suspension’s damping when it is being released.
+ *
+ * Increase this value if the suspension appears to overshoot.
+ */
+ public setWheelSuspensionRelaxation(i: number, value: number) {
+ this.raw.set_wheel_suspension_relaxation(i, value);
+ }
+
+ /**
+ * The maximum force applied by the i-th wheel’s suspension.
+ */
+ public wheelMaxSuspensionForce(i: number): number | null {
+ return this.raw.wheel_max_suspension_force(i);
+ }
+
+ /**
+ * Sets the maximum force applied by the i-th wheel’s suspension.
+ */
+ public setWheelMaxSuspensionForce(i: number, value: number) {
+ this.raw.set_wheel_max_suspension_force(i, value);
+ }
+
+ /**
+ * The maximum amount of braking impulse applied on the i-th wheel to slow down the vehicle.
+ */
+ public wheelBrake(i: number): number | null {
+ return this.raw.wheel_brake(i);
+ }
+
+ /**
+ * Set the maximum amount of braking impulse applied on the i-th wheel to slow down the vehicle.
+ */
+ public setWheelBrake(i: number, value: number) {
+ this.raw.set_wheel_brake(i, value);
+ }
+
+ /**
+ * The steering angle (radians) for the i-th wheel.
+ */
+ public wheelSteering(i: number): number | null {
+ return this.raw.wheel_steering(i);
+ }
+
+ /**
+ * Sets the steering angle (radians) for the i-th wheel.
+ */
+ public setWheelSteering(i: number, value: number) {
+ this.raw.set_wheel_steering(i, value);
+ }
+
+ /**
+ * The forward force applied by the i-th wheel on the chassis.
+ */
+ public wheelEngineForce(i: number): number | null {
+ return this.raw.wheel_engine_force(i);
+ }
+
+ /**
+ * Sets the forward force applied by the i-th wheel on the chassis.
+ */
+ public setWheelEngineForce(i: number, value: number) {
+ this.raw.set_wheel_engine_force(i, value);
+ }
+
+ /**
+ * The direction of the i-th wheel’s suspension, relative to the chassis.
+ *
+ * The ray-casting will happen following this direction to detect the ground.
+ *
+ * @param {number} i
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public wheelDirectionCs(i: number, target?: Vector): Vector | null {
+ const exists = this.raw.wheel_direction_cs(i, scratchBuffer);
+ return exists ? VectorOps.fromBuffer(scratchBuffer, target) : null;
+ }
+
+ /**
+ * Sets the direction of the i-th wheel’s suspension, relative to the chassis.
+ *
+ * The ray-casting will happen following this direction to detect the ground.
+ */
+ public setWheelDirectionCs(i: number, value: Vector) {
+ let rawValue = VectorOps.intoRaw(value);
+ this.raw.set_wheel_direction_cs(i, rawValue);
+ rawValue.free();
+ }
+
+ /**
+ * The i-th wheel’s axle axis, relative to the chassis.
+ *
+ * The axis index defined as 0 = X, 1 = Y, 2 = Z.
+ *
+ * @param {number} i
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public wheelAxleCs(i: number, target?: Vector): Vector | null {
+ const exists = this.raw.wheel_axle_cs(i, scratchBuffer);
+ return exists ? VectorOps.fromBuffer(scratchBuffer, target) : null;
+ }
+
+ /**
+ * Sets the i-th wheel’s axle axis, relative to the chassis.
+ *
+ * The axis index defined as 0 = X, 1 = Y, 2 = Z.
+ */
+ public setWheelAxleCs(i: number, value: Vector) {
+ let rawValue = VectorOps.intoRaw(value);
+ this.raw.set_wheel_axle_cs(i, rawValue);
+ rawValue.free();
+ }
+
+ /**
+ * Parameter controlling how much traction the tire has.
+ *
+ * The larger the value, the more instantaneous braking will happen (with the risk of
+ * causing the vehicle to flip if it’s too strong).
+ */
+ public wheelFrictionSlip(i: number): number | null {
+ return this.raw.wheel_friction_slip(i);
+ }
+
+ /**
+ * Sets the parameter controlling how much traction the tire has.
+ *
+ * The larger the value, the more instantaneous braking will happen (with the risk of
+ * causing the vehicle to flip if it’s too strong).
+ */
+ public setWheelFrictionSlip(i: number, value: number) {
+ this.raw.set_wheel_friction_slip(i, value);
+ }
+
+ /**
+ * The multiplier of friction between a tire and the collider it’s on top of.
+ *
+ * The larger the value, the stronger side friction will be.
+ */
+ public wheelSideFrictionStiffness(i: number): number | null {
+ return this.raw.wheel_side_friction_stiffness(i);
+ }
+
+ /**
+ * The multiplier of friction between a tire and the collider it’s on top of.
+ *
+ * The larger the value, the stronger side friction will be.
+ */
+ public setWheelSideFrictionStiffness(i: number, value: number) {
+ this.raw.set_wheel_side_friction_stiffness(i, value);
+ }
+
+ /*
+ * Getters only.
+ */
+
+ /**
+ * The i-th wheel’s current rotation angle (radians) on its axle.
+ */
+ public wheelRotation(i: number): number | null {
+ return this.raw.wheel_rotation(i);
+ }
+
+ /**
+ * The forward impulses applied by the i-th wheel on the chassis.
+ */
+ public wheelForwardImpulse(i: number): number | null {
+ return this.raw.wheel_forward_impulse(i);
+ }
+
+ /**
+ * The side impulses applied by the i-th wheel on the chassis.
+ */
+ public wheelSideImpulse(i: number): number | null {
+ return this.raw.wheel_side_impulse(i);
+ }
+
+ /**
+ * The force applied by the i-th wheel suspension.
+ */
+ public wheelSuspensionForce(i: number): number | null {
+ return this.raw.wheel_suspension_force(i);
+ }
+
+ /**
+ * The (world-space) contact normal between the i-th wheel and the floor.
+ *
+ * @param {number} i
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public wheelContactNormal(i: number, target?: Vector): Vector | null {
+ const exists = this.raw.wheel_contact_normal_ws(i, scratchBuffer);
+ return exists ? VectorOps.fromBuffer(scratchBuffer, target) : null;
+ }
+
+ /**
+ * The (world-space) point hit by the wheel’s ray-cast for the i-th wheel.
+ *
+ * @param {number} i
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public wheelContactPoint(i: number, target?: Vector): Vector | null {
+ const exists = this.raw.wheel_contact_point_ws(i, scratchBuffer);
+ return exists ? VectorOps.fromBuffer(scratchBuffer, target) : null;
+ }
+
+ /**
+ * The suspension length for the i-th wheel.
+ */
+ public wheelSuspensionLength(i: number): number | null {
+ return this.raw.wheel_suspension_length(i);
+ }
+
+ /**
+ * The (world-space) starting point of the ray-cast for the i-th wheel.
+ *
+ * @param {number} i
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public wheelHardPoint(i: number, target?: Vector): Vector | null {
+ const exists = this.raw.wheel_hard_point_ws(i, scratchBuffer);
+ return exists ? VectorOps.fromBuffer(scratchBuffer, target) : null;
+ }
+
+ /**
+ * Is the i-th wheel in contact with the ground?
+ */
+ public wheelIsInContact(i: number): boolean {
+ return this.raw.wheel_is_in_contact(i);
+ }
+
+ /**
+ * The collider hit by the ray-cast for the i-th wheel.
+ */
+ public wheelGroundObject(i: number): Collider | null {
+ return this.colliders.get(this.raw.wheel_ground_object(i));
+ }
+}
diff --git a/typescript/src.ts/dynamics/ccd_solver.ts b/typescript/src.ts/dynamics/ccd_solver.ts
new file mode 100644
index 000000000..7f7942224
--- /dev/null
+++ b/typescript/src.ts/dynamics/ccd_solver.ts
@@ -0,0 +1,25 @@
+import {RawCCDSolver} from "../raw";
+
+/**
+ * The CCD solver responsible for resolving Continuous Collision Detection.
+ *
+ * To avoid leaking WASM resources, this MUST be freed manually with `ccdSolver.free()`
+ * once you are done using it.
+ */
+export class CCDSolver {
+ raw: RawCCDSolver;
+
+ /**
+ * Release the WASM memory occupied by this narrow-phase.
+ */
+ public free() {
+ if (!!this.raw) {
+ this.raw.free();
+ }
+ this.raw = undefined;
+ }
+
+ constructor(raw?: RawCCDSolver) {
+ this.raw = raw || new RawCCDSolver();
+ }
+}
diff --git a/typescript/src.ts/dynamics/coefficient_combine_rule.ts b/typescript/src.ts/dynamics/coefficient_combine_rule.ts
new file mode 100644
index 000000000..680b402a9
--- /dev/null
+++ b/typescript/src.ts/dynamics/coefficient_combine_rule.ts
@@ -0,0 +1,13 @@
+/**
+ * A rule applied to combine coefficients.
+ *
+ * Use this when configuring the `ColliderDesc` to specify
+ * how friction and restitution coefficient should be combined
+ * in a contact.
+ */
+export enum CoefficientCombineRule {
+ Average = 0,
+ Min = 1,
+ Multiply = 2,
+ Max = 3,
+}
diff --git a/typescript/src.ts/dynamics/impulse_joint.ts b/typescript/src.ts/dynamics/impulse_joint.ts
new file mode 100644
index 000000000..68185efeb
--- /dev/null
+++ b/typescript/src.ts/dynamics/impulse_joint.ts
@@ -0,0 +1,794 @@
+import {Rotation, Vector, VectorOps, RotationOps, scratchBuffer} from "../math";
+import {
+ RawGenericJoint,
+ RawImpulseJointSet,
+ RawRigidBodySet,
+ RawJointAxis,
+ RawJointType,
+ RawMotorModel,
+} from "../raw";
+import {RigidBody, RigidBodyHandle} from "./rigid_body";
+import {RigidBodySet} from "./rigid_body_set";
+// #if DIM3
+import {Quaternion} from "../math";
+// #endif
+
+/**
+ * The integer identifier of a collider added to a `ColliderSet`.
+ */
+export type ImpulseJointHandle = number;
+
+/**
+ * An enum grouping all possible types of joints:
+ *
+ * - `Revolute`: A revolute joint that removes all degrees of freedom between the affected
+ * bodies except for the rotation along one axis.
+ * - `Fixed`: A fixed joint that removes all relative degrees of freedom between the affected bodies.
+ * - `Prismatic`: A prismatic joint that removes all degrees of freedom between the affected
+ * bodies except for the translation along one axis.
+ * - `Spherical`: (3D only) A spherical joint that removes all relative linear degrees of freedom between the affected bodies.
+ * - `Generic`: (3D only) A joint with customizable degrees of freedom, allowing any of the 6 axes to be locked.
+ */
+export enum JointType {
+ Revolute,
+ Fixed,
+ Prismatic,
+ Rope,
+ Spring,
+ // #if DIM3
+ Spherical,
+ Generic,
+ // #endif
+}
+
+export enum MotorModel {
+ AccelerationBased,
+ ForceBased,
+}
+
+/**
+ * An enum representing the possible joint axes of a generic joint.
+ * They can be ORed together, like:
+ * JointAxesMask.LinX || JointAxesMask.LinY
+ * to get a joint that is only free in the X and Y translational (positional) axes.
+ *
+ * Possible free axes are:
+ *
+ * - `X`: X translation axis
+ * - `Y`: Y translation axis
+ * - `Z`: Z translation axis
+ * - `AngX`: X angular rotation axis
+ * - `AngY`: Y angular rotations axis
+ * - `AngZ`: Z angular rotation axis
+ */
+export enum JointAxesMask {
+ LinX = 1 << 0,
+ LinY = 1 << 1,
+ LinZ = 1 << 2,
+ AngX = 1 << 3,
+ AngY = 1 << 4,
+ AngZ = 1 << 5,
+}
+
+export class ImpulseJoint {
+ protected rawSet: RawImpulseJointSet; // The ImpulseJoint won't need to free this.
+ protected bodySet: RigidBodySet; // The ImpulseJoint won’t need to free this.
+ handle: ImpulseJointHandle;
+
+ constructor(
+ rawSet: RawImpulseJointSet,
+ bodySet: RigidBodySet,
+ handle: ImpulseJointHandle,
+ ) {
+ this.rawSet = rawSet;
+ this.bodySet = bodySet;
+ this.handle = handle;
+ }
+
+ public static newTyped(
+ rawSet: RawImpulseJointSet,
+ bodySet: RigidBodySet,
+ handle: ImpulseJointHandle,
+ ): ImpulseJoint {
+ switch (rawSet.jointType(handle)) {
+ case RawJointType.Revolute:
+ return new RevoluteImpulseJoint(rawSet, bodySet, handle);
+ case RawJointType.Prismatic:
+ return new PrismaticImpulseJoint(rawSet, bodySet, handle);
+ case RawJointType.Fixed:
+ return new FixedImpulseJoint(rawSet, bodySet, handle);
+ case RawJointType.Spring:
+ return new SpringImpulseJoint(rawSet, bodySet, handle);
+ case RawJointType.Rope:
+ return new RopeImpulseJoint(rawSet, bodySet, handle);
+ // #if DIM3
+ case RawJointType.Spherical:
+ return new SphericalImpulseJoint(rawSet, bodySet, handle);
+ case RawJointType.Generic:
+ return new GenericImpulseJoint(rawSet, bodySet, handle);
+ // #endif
+ default:
+ return new ImpulseJoint(rawSet, bodySet, handle);
+ }
+ }
+
+ /** @internal */
+ public finalizeDeserialization(bodySet: RigidBodySet) {
+ this.bodySet = bodySet;
+ }
+
+ /**
+ * Checks if this joint is still valid (i.e. that it has
+ * not been deleted from the joint set yet).
+ */
+ public isValid(): boolean {
+ return this.rawSet.contains(this.handle);
+ }
+
+ /**
+ * The first rigid-body this joint it attached to.
+ */
+ public body1(): RigidBody {
+ return this.bodySet.get(this.rawSet.jointBodyHandle1(this.handle));
+ }
+
+ /**
+ * The second rigid-body this joint is attached to.
+ */
+ public body2(): RigidBody {
+ return this.bodySet.get(this.rawSet.jointBodyHandle2(this.handle));
+ }
+
+ /**
+ * The type of this joint given as a string.
+ */
+ public type(): JointType {
+ return this.rawSet.jointType(this.handle) as number as JointType;
+ }
+
+ // #if DIM3
+ /**
+ * The rotation quaternion that aligns this joint's first local axis to the `x` axis.
+ *
+ * @param {Rotation?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public frameX1(target?: Rotation): Rotation {
+ this.rawSet.jointFrameX1(this.handle, scratchBuffer);
+ return RotationOps.fromBuffer(scratchBuffer, target);
+ }
+
+ // #endif
+
+ // #if DIM3
+ /**
+ * The rotation matrix that aligns this joint's second local axis to the `x` axis.
+ *
+ * @param {Rotation?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public frameX2(target?: Rotation): Rotation {
+ this.rawSet.jointFrameX2(this.handle, scratchBuffer);
+ return RotationOps.fromBuffer(scratchBuffer, target);
+ }
+
+ // #endif
+
+ /**
+ * The position of the first anchor of this joint.
+ *
+ * The first anchor gives the position of the application point on the
+ * local frame of the first rigid-body it is attached to.
+ *
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public anchor1(target?: Vector): Vector {
+ this.rawSet.jointAnchor1(this.handle, scratchBuffer);
+ return VectorOps.fromBuffer(scratchBuffer, target);
+ }
+
+ /**
+ * The position of the second anchor of this joint.
+ *
+ * The second anchor gives the position of the application point on the
+ * local frame of the second rigid-body it is attached to.
+ *
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public anchor2(target?: Vector): Vector {
+ this.rawSet.jointAnchor2(this.handle, scratchBuffer);
+ return VectorOps.fromBuffer(scratchBuffer, target);
+ }
+
+ /**
+ * Sets the position of the first anchor of this joint.
+ *
+ * The first anchor gives the position of the application point on the
+ * local frame of the first rigid-body it is attached to.
+ */
+ public setAnchor1(newPos: Vector) {
+ const rawPoint = VectorOps.intoRaw(newPos);
+ this.rawSet.jointSetAnchor1(this.handle, rawPoint);
+ rawPoint.free();
+ }
+
+ /**
+ * Sets the position of the second anchor of this joint.
+ *
+ * The second anchor gives the position of the application point on the
+ * local frame of the second rigid-body it is attached to.
+ */
+ public setAnchor2(newPos: Vector) {
+ const rawPoint = VectorOps.intoRaw(newPos);
+ this.rawSet.jointSetAnchor2(this.handle, rawPoint);
+ rawPoint.free();
+ }
+
+ // #if DIM3
+ /**
+ * Sets the rotation quaternion that aligns this joint's first local axis to the `x` axis.
+ */
+ public setFrameX1(rot: Rotation) {
+ const rawRot = RotationOps.intoRaw(rot);
+ this.rawSet.jointSetFrameX1(this.handle, rawRot);
+ rawRot.free();
+ }
+
+ /**
+ * Sets the rotation quaternion that aligns this joint's second local axis to the `x` axis.
+ */
+ public setFrameX2(rot: Rotation) {
+ const rawRot = RotationOps.intoRaw(rot);
+ this.rawSet.jointSetFrameX2(this.handle, rawRot);
+ rawRot.free();
+ }
+
+ /**
+ * Sets the full local frame (anchor position and rotation) for the first rigid-body attachment.
+ */
+ public setLocalFrame1(anchor: Vector, rot: Rotation) {
+ const rawAnchor = VectorOps.intoRaw(anchor);
+ const rawRot = RotationOps.intoRaw(rot);
+ this.rawSet.jointSetLocalFrame1(this.handle, rawAnchor, rawRot);
+ rawAnchor.free();
+ rawRot.free();
+ }
+
+ /**
+ * Sets the full local frame (anchor position and rotation) for the second rigid-body attachment.
+ */
+ public setLocalFrame2(anchor: Vector, rot: Rotation) {
+ const rawAnchor = VectorOps.intoRaw(anchor);
+ const rawRot = RotationOps.intoRaw(rot);
+ this.rawSet.jointSetLocalFrame2(this.handle, rawAnchor, rawRot);
+ rawAnchor.free();
+ rawRot.free();
+ }
+ // #endif
+
+ /**
+ * Controls whether contacts are computed between colliders attached
+ * to the rigid-bodies linked by this joint.
+ */
+ public setContactsEnabled(enabled: boolean) {
+ this.rawSet.jointSetContactsEnabled(this.handle, enabled);
+ }
+
+ /**
+ * Indicates if contacts are enabled between colliders attached
+ * to the rigid-bodies linked by this joint.
+ */
+ public contactsEnabled(): boolean {
+ return this.rawSet.jointContactsEnabled(this.handle);
+ }
+}
+
+export class UnitImpulseJoint extends ImpulseJoint {
+ /**
+ * The axis left free by this joint.
+ */
+ protected rawAxis?(): RawJointAxis;
+
+ /**
+ * Are the limits enabled for this joint?
+ */
+ public limitsEnabled(): boolean {
+ return this.rawSet.jointLimitsEnabled(this.handle, this.rawAxis());
+ }
+
+ /**
+ * The min limit of this joint.
+ */
+ public limitsMin(): number {
+ return this.rawSet.jointLimitsMin(this.handle, this.rawAxis());
+ }
+
+ /**
+ * The max limit of this joint.
+ */
+ public limitsMax(): number {
+ return this.rawSet.jointLimitsMax(this.handle, this.rawAxis());
+ }
+
+ /**
+ * Sets the limits of this joint.
+ *
+ * @param min - The minimum bound of this joint’s free coordinate.
+ * @param max - The maximum bound of this joint’s free coordinate.
+ */
+ public setLimits(min: number, max: number) {
+ this.rawSet.jointSetLimits(this.handle, this.rawAxis(), min, max);
+ }
+
+ public configureMotorModel(model: MotorModel) {
+ this.rawSet.jointConfigureMotorModel(
+ this.handle,
+ this.rawAxis(),
+ model as number as RawMotorModel,
+ );
+ }
+
+ public setMotorMaxForce(maxForce: number) {
+ this.rawSet.jointSetMotorMaxForce(
+ this.handle,
+ this.rawAxis(),
+ maxForce,
+ );
+ }
+
+ public configureMotorVelocity(targetVel: number, factor: number) {
+ this.rawSet.jointConfigureMotorVelocity(
+ this.handle,
+ this.rawAxis(),
+ targetVel,
+ factor,
+ );
+ }
+
+ public configureMotorPosition(
+ targetPos: number,
+ stiffness: number,
+ damping: number,
+ ) {
+ this.rawSet.jointConfigureMotorPosition(
+ this.handle,
+ this.rawAxis(),
+ targetPos,
+ stiffness,
+ damping,
+ );
+ }
+
+ public configureMotor(
+ targetPos: number,
+ targetVel: number,
+ stiffness: number,
+ damping: number,
+ ) {
+ this.rawSet.jointConfigureMotor(
+ this.handle,
+ this.rawAxis(),
+ targetPos,
+ targetVel,
+ stiffness,
+ damping,
+ );
+ }
+}
+
+export class FixedImpulseJoint extends ImpulseJoint {}
+
+export class RopeImpulseJoint extends ImpulseJoint {}
+
+export class SpringImpulseJoint extends ImpulseJoint {}
+
+export class PrismaticImpulseJoint extends UnitImpulseJoint {
+ public rawAxis(): RawJointAxis {
+ return RawJointAxis.LinX;
+ }
+}
+
+export class RevoluteImpulseJoint extends UnitImpulseJoint {
+ public rawAxis(): RawJointAxis {
+ return RawJointAxis.AngX;
+ }
+}
+
+// #if DIM3
+export class GenericImpulseJoint extends ImpulseJoint {}
+
+export class SphericalImpulseJoint extends ImpulseJoint {
+ /* Unsupported by this alpha release.
+ public configureMotorModel(model: MotorModel) {
+ this.rawSet.jointConfigureMotorModel(this.handle, model);
+ }
+
+ public configureMotorVelocity(targetVel: Vector, factor: number) {
+ this.rawSet.jointConfigureBallMotorVelocity(this.handle, targetVel.x, targetVel.y, targetVel.z, factor);
+ }
+
+ public configureMotorPosition(targetPos: Quaternion, stiffness: number, damping: number) {
+ this.rawSet.jointConfigureBallMotorPosition(this.handle, targetPos.w, targetPos.x, targetPos.y, targetPos.z, stiffness, damping);
+ }
+
+ public configureMotor(targetPos: Quaternion, targetVel: Vector, stiffness: number, damping: number) {
+ this.rawSet.jointConfigureBallMotor(this.handle,
+ targetPos.w, targetPos.x, targetPos.y, targetPos.z,
+ targetVel.x, targetVel.y, targetVel.z,
+ stiffness, damping);
+ }
+ */
+}
+// #endif
+
+export class JointData {
+ anchor1: Vector;
+ anchor2: Vector;
+ axis: Vector;
+ // #if DIM3
+ axis1: Vector;
+ axis2: Vector;
+ // #endif
+ frame1: Rotation;
+ frame2: Rotation;
+ jointType: JointType;
+ limitsEnabled: boolean;
+ limits: Array;
+ axesMask: JointAxesMask;
+ stiffness: number;
+ damping: number;
+ length: number;
+
+ private constructor() {}
+
+ /**
+ * Creates a new joint descriptor that builds a Fixed joint.
+ *
+ * A fixed joint removes all the degrees of freedom between the affected bodies, ensuring their
+ * anchor and local frames coincide in world-space.
+ *
+ * @param anchor1 - Point where the joint is attached on the first rigid-body affected by this joint. Expressed in the
+ * local-space of the rigid-body.
+ * @param frame1 - The reference orientation of the joint wrt. the first rigid-body.
+ * @param anchor2 - Point where the joint is attached on the second rigid-body affected by this joint. Expressed in the
+ * local-space of the rigid-body.
+ * @param frame2 - The reference orientation of the joint wrt. the second rigid-body.
+ */
+ public static fixed(
+ anchor1: Vector,
+ frame1: Rotation,
+ anchor2: Vector,
+ frame2: Rotation,
+ ): JointData {
+ let res = new JointData();
+ res.anchor1 = anchor1;
+ res.anchor2 = anchor2;
+ res.frame1 = frame1;
+ res.frame2 = frame2;
+ res.jointType = JointType.Fixed;
+ return res;
+ }
+
+ public static spring(
+ rest_length: number,
+ stiffness: number,
+ damping: number,
+ anchor1: Vector,
+ anchor2: Vector,
+ ): JointData {
+ let res = new JointData();
+ res.anchor1 = anchor1;
+ res.anchor2 = anchor2;
+ res.length = rest_length;
+ res.stiffness = stiffness;
+ res.damping = damping;
+ res.jointType = JointType.Spring;
+ return res;
+ }
+
+ public static rope(
+ length: number,
+ anchor1: Vector,
+ anchor2: Vector,
+ ): JointData {
+ let res = new JointData();
+ res.anchor1 = anchor1;
+ res.anchor2 = anchor2;
+ res.length = length;
+ res.jointType = JointType.Rope;
+ return res;
+ }
+
+ // #if DIM2
+
+ /**
+ * Create a new joint descriptor that builds revolute joints.
+ *
+ * A revolute joint allows three relative rotational degrees of freedom
+ * by preventing any relative translation between the anchors of the
+ * two attached rigid-bodies.
+ *
+ * @param anchor1 - Point where the joint is attached on the first rigid-body affected by this joint. Expressed in the
+ * local-space of the rigid-body.
+ * @param anchor2 - Point where the joint is attached on the second rigid-body affected by this joint. Expressed in the
+ * local-space of the rigid-body.
+ */
+ public static revolute(anchor1: Vector, anchor2: Vector): JointData {
+ let res = new JointData();
+ res.anchor1 = anchor1;
+ res.anchor2 = anchor2;
+ res.jointType = JointType.Revolute;
+ return res;
+ }
+
+ /**
+ * Creates a new joint descriptor that builds a Prismatic joint.
+ *
+ * A prismatic joint removes all the degrees of freedom between the
+ * affected bodies, except for the translation along one axis.
+ *
+ * @param anchor1 - Point where the joint is attached on the first rigid-body affected by this joint. Expressed in the
+ * local-space of the rigid-body.
+ * @param anchor2 - Point where the joint is attached on the second rigid-body affected by this joint. Expressed in the
+ * local-space of the rigid-body.
+ * @param axis - Axis of the joint, expressed in the local-space of the rigid-bodies it is attached to.
+ */
+ public static prismatic(
+ anchor1: Vector,
+ anchor2: Vector,
+ axis: Vector,
+ ): JointData {
+ let res = new JointData();
+ res.anchor1 = anchor1;
+ res.anchor2 = anchor2;
+ res.axis = axis;
+ res.jointType = JointType.Prismatic;
+ return res;
+ }
+
+ // #endif
+
+ // #if DIM3
+ /**
+ * Create a new joint descriptor that builds generic joints.
+ *
+ * A generic joint allows customizing its degrees of freedom
+ * by supplying a mask of the joint axes that should remain locked.
+ *
+ * @param anchor1 - Point where the joint is attached on the first rigid-body affected by this joint. Expressed in the
+ * local-space of the rigid-body.
+ * @param anchor2 - Point where the joint is attached on the second rigid-body affected by this joint. Expressed in the
+ * local-space of the rigid-body.
+ * @param axis - The X axis of the joint, expressed in the local-space of the rigid-bodies it is attached to.
+ * @param axesMask - Mask representing the locked axes of the joint. You can use logical OR to select these from
+ * the JointAxesMask enum. For example, passing (JointAxesMask.AngX || JointAxesMask.AngY) will
+ * create a joint locked in the X and Y rotational axes.
+ */
+ public static generic(
+ anchor1: Vector,
+ anchor2: Vector,
+ axis: Vector,
+ axesMask: JointAxesMask,
+ ): JointData {
+ let res = new JointData();
+ res.anchor1 = anchor1;
+ res.anchor2 = anchor2;
+ res.axis = axis;
+ res.axesMask = axesMask;
+ res.jointType = JointType.Generic;
+ return res;
+ }
+
+ /**
+ * Create a new joint descriptor that builds spherical joints.
+ *
+ * A spherical joint allows three relative rotational degrees of freedom
+ * by preventing any relative translation between the anchors of the
+ * two attached rigid-bodies.
+ *
+ * @param anchor1 - Point where the joint is attached on the first rigid-body affected by this joint. Expressed in the
+ * local-space of the rigid-body.
+ * @param anchor2 - Point where the joint is attached on the second rigid-body affected by this joint. Expressed in the
+ * local-space of the rigid-body.
+ */
+ public static spherical(anchor1: Vector, anchor2: Vector): JointData {
+ let res = new JointData();
+ res.anchor1 = anchor1;
+ res.anchor2 = anchor2;
+ res.jointType = JointType.Spherical;
+ return res;
+ }
+
+ /**
+ * Creates a new joint descriptor that builds a Prismatic joint.
+ *
+ * A prismatic joint removes all the degrees of freedom between the
+ * affected bodies, except for the translation along one axis.
+ *
+ * @param anchor1 - Point where the joint is attached on the first rigid-body affected by this joint. Expressed in the
+ * local-space of the rigid-body.
+ * @param anchor2 - Point where the joint is attached on the second rigid-body affected by this joint. Expressed in the
+ * local-space of the rigid-body.
+ * @param axis - Axis of the joint, expressed in the local-space of the rigid-bodies it is attached to.
+ */
+ public static prismatic(
+ anchor1: Vector,
+ anchor2: Vector,
+ axis: Vector,
+ ): JointData {
+ let res = new JointData();
+ res.anchor1 = anchor1;
+ res.anchor2 = anchor2;
+ res.axis = axis;
+ res.jointType = JointType.Prismatic;
+ return res;
+ }
+
+ /**
+ * Create a new joint descriptor that builds Revolute joints.
+ *
+ * A revolute joint removes all degrees of freedom between the affected
+ * bodies except for the rotation along one axis.
+ *
+ * @param anchor1 - Point where the joint is attached on the first rigid-body affected by this joint. Expressed in the
+ * local-space of the rigid-body.
+ * @param anchor2 - Point where the joint is attached on the second rigid-body affected by this joint. Expressed in the
+ * local-space of the rigid-body.
+ * @param axis - Axis of the joint, expressed in the local-space of the rigid-bodies it is attached to.
+ */
+ public static revolute(
+ anchor1: Vector,
+ anchor2: Vector,
+ axis: Vector,
+ ): JointData {
+ let res = new JointData();
+ res.anchor1 = anchor1;
+ res.anchor2 = anchor2;
+ res.axis = axis;
+ res.jointType = JointType.Revolute;
+ return res;
+ }
+
+ /**
+ * Create a new joint descriptor that builds Revolute joints with independent
+ * local axes for each attached rigid-body.
+ *
+ * This is useful when the same world-space hinge axis is represented by
+ * different local axes on the two bodies.
+ *
+ * @param anchor1 - Point where the joint is attached on the first rigid-body affected by this joint. Expressed in the
+ * local-space of the rigid-body.
+ * @param anchor2 - Point where the joint is attached on the second rigid-body affected by this joint. Expressed in the
+ * local-space of the rigid-body.
+ * @param axis1 - Axis of the joint, expressed in the local-space of the first rigid-body.
+ * @param axis2 - Axis of the joint, expressed in the local-space of the second rigid-body.
+ */
+ public static revoluteWithAxes(
+ anchor1: Vector,
+ anchor2: Vector,
+ axis1: Vector,
+ axis2: Vector,
+ ): JointData {
+ let res = new JointData();
+ res.anchor1 = anchor1;
+ res.anchor2 = anchor2;
+ res.axis = axis1;
+ res.axis1 = axis1;
+ res.axis2 = axis2;
+ res.jointType = JointType.Revolute;
+ return res;
+ }
+ // #endif
+
+ public intoRaw(): RawGenericJoint {
+ let rawA1 = VectorOps.intoRaw(this.anchor1);
+ let rawA2 = VectorOps.intoRaw(this.anchor2);
+ let rawAx;
+ let result;
+ let limitsEnabled = false;
+ let limitsMin = 0.0;
+ let limitsMax = 0.0;
+
+ switch (this.jointType) {
+ case JointType.Fixed:
+ let rawFra1 = RotationOps.intoRaw(this.frame1);
+ let rawFra2 = RotationOps.intoRaw(this.frame2);
+ result = RawGenericJoint.fixed(rawA1, rawFra1, rawA2, rawFra2);
+ rawFra1.free();
+ rawFra2.free();
+ break;
+ case JointType.Spring:
+ result = RawGenericJoint.spring(
+ this.length,
+ this.stiffness,
+ this.damping,
+ rawA1,
+ rawA2,
+ );
+ break;
+ case JointType.Rope:
+ result = RawGenericJoint.rope(this.length, rawA1, rawA2);
+ break;
+ case JointType.Prismatic:
+ rawAx = VectorOps.intoRaw(this.axis);
+
+ if (!!this.limitsEnabled) {
+ limitsEnabled = true;
+ limitsMin = this.limits[0];
+ limitsMax = this.limits[1];
+ }
+
+ // #if DIM2
+ result = RawGenericJoint.prismatic(
+ rawA1,
+ rawA2,
+ rawAx,
+ limitsEnabled,
+ limitsMin,
+ limitsMax,
+ );
+ // #endif
+
+ // #if DIM3
+ result = RawGenericJoint.prismatic(
+ rawA1,
+ rawA2,
+ rawAx,
+ limitsEnabled,
+ limitsMin,
+ limitsMax,
+ );
+ // #endif
+
+ rawAx.free();
+ break;
+ // #if DIM2
+ case JointType.Revolute:
+ result = RawGenericJoint.revolute(rawA1, rawA2);
+ break;
+ // #endif
+ // #if DIM3
+ case JointType.Generic:
+ rawAx = VectorOps.intoRaw(this.axis);
+ // implicit type cast: axesMask is a JointAxesMask bitflag enum,
+ // we're treating it as a u8 on the Rust side
+ let rawAxesMask = this.axesMask;
+ result = RawGenericJoint.generic(
+ rawA1,
+ rawA2,
+ rawAx,
+ rawAxesMask,
+ );
+ break;
+ case JointType.Spherical:
+ result = RawGenericJoint.spherical(rawA1, rawA2);
+ break;
+ case JointType.Revolute:
+ if (!!this.axis1 && !!this.axis2) {
+ let rawAx1 = VectorOps.intoRaw(this.axis1);
+ let rawAx2 = VectorOps.intoRaw(this.axis2);
+ result = RawGenericJoint.revoluteWithAxes(
+ rawA1,
+ rawA2,
+ rawAx1,
+ rawAx2,
+ );
+ rawAx1.free();
+ rawAx2.free();
+ } else {
+ rawAx = VectorOps.intoRaw(this.axis);
+ result = RawGenericJoint.revolute(rawA1, rawA2, rawAx);
+ rawAx.free();
+ }
+ break;
+ // #endif
+ }
+
+ rawA1.free();
+ rawA2.free();
+
+ return result;
+ }
+}
diff --git a/typescript/src.ts/dynamics/impulse_joint_set.ts b/typescript/src.ts/dynamics/impulse_joint_set.ts
new file mode 100644
index 000000000..2d382514b
--- /dev/null
+++ b/typescript/src.ts/dynamics/impulse_joint_set.ts
@@ -0,0 +1,165 @@
+import {RawImpulseJointSet} from "../raw";
+import {Coarena} from "../coarena";
+import {RigidBodySet} from "./rigid_body_set";
+import {
+ RevoluteImpulseJoint,
+ FixedImpulseJoint,
+ ImpulseJoint,
+ ImpulseJointHandle,
+ JointData,
+ JointType,
+ PrismaticImpulseJoint,
+ // #if DIM3
+ SphericalImpulseJoint,
+ // #endif
+} from "./impulse_joint";
+import {IslandManager} from "./island_manager";
+import {RigidBodyHandle} from "./rigid_body";
+import {Collider, ColliderHandle} from "../geometry";
+
+/**
+ * A set of joints.
+ *
+ * To avoid leaking WASM resources, this MUST be freed manually with `jointSet.free()`
+ * once you are done using it (and all the joints it created).
+ */
+export class ImpulseJointSet {
+ raw: RawImpulseJointSet;
+ private map: Coarena;
+
+ /**
+ * Release the WASM memory occupied by this joint set.
+ */
+ public free() {
+ if (!!this.raw) {
+ this.raw.free();
+ }
+ this.raw = undefined;
+
+ if (!!this.map) {
+ this.map.clear();
+ }
+ this.map = undefined;
+ }
+
+ constructor(raw?: RawImpulseJointSet) {
+ this.raw = raw || new RawImpulseJointSet();
+ this.map = new Coarena();
+ // Initialize the map with the existing elements, if any.
+ if (raw) {
+ raw.forEachJointHandle((handle: ImpulseJointHandle) => {
+ this.map.set(handle, ImpulseJoint.newTyped(raw, null, handle));
+ });
+ }
+ }
+
+ /** @internal */
+ public finalizeDeserialization(bodies: RigidBodySet) {
+ this.map.forEach((joint) => joint.finalizeDeserialization(bodies));
+ }
+
+ /**
+ * Creates a new joint and return its integer handle.
+ *
+ * @param bodies - The set of rigid-bodies containing the bodies the joint is attached to.
+ * @param desc - The joint's parameters.
+ * @param parent1 - The handle of the first rigid-body this joint is attached to.
+ * @param parent2 - The handle of the second rigid-body this joint is attached to.
+ * @param wakeUp - Should the attached rigid-bodies be awakened?
+ */
+ public createJoint(
+ bodies: RigidBodySet,
+ desc: JointData,
+ parent1: RigidBodyHandle,
+ parent2: RigidBodyHandle,
+ wakeUp: boolean,
+ ): ImpulseJoint {
+ const rawParams = desc.intoRaw();
+ const handle = this.raw.createJoint(
+ rawParams,
+ parent1,
+ parent2,
+ wakeUp,
+ );
+ rawParams.free();
+ let joint = ImpulseJoint.newTyped(this.raw, bodies, handle);
+ this.map.set(handle, joint);
+ return joint;
+ }
+
+ /**
+ * Remove a joint from this set.
+ *
+ * @param handle - The integer handle of the joint.
+ * @param wakeUp - If `true`, the rigid-bodies attached by the removed joint will be woken-up automatically.
+ */
+ public remove(handle: ImpulseJointHandle, wakeUp: boolean) {
+ this.raw.remove(handle, wakeUp);
+ this.unmap(handle);
+ }
+
+ /**
+ * Calls the given closure with the integer handle of each impulse joint attached to this rigid-body.
+ *
+ * @param f - The closure called with the integer handle of each impulse joint attached to the rigid-body.
+ */
+ public forEachJointHandleAttachedToRigidBody(
+ handle: RigidBodyHandle,
+ f: (handle: ImpulseJointHandle) => void,
+ ) {
+ this.raw.forEachJointAttachedToRigidBody(handle, f);
+ }
+
+ /**
+ * Internal function, do not call directly.
+ * @param handle
+ */
+ public unmap(handle: ImpulseJointHandle) {
+ this.map.delete(handle);
+ }
+
+ /**
+ * The number of joints on this set.
+ */
+ public len(): number {
+ return this.map.len();
+ }
+
+ /**
+ * Does this set contain a joint with the given handle?
+ *
+ * @param handle - The joint handle to check.
+ */
+ public contains(handle: ImpulseJointHandle): boolean {
+ return this.get(handle) != null;
+ }
+
+ /**
+ * Gets the joint with the given handle.
+ *
+ * Returns `null` if no joint with the specified handle exists.
+ *
+ * @param handle - The integer handle of the joint to retrieve.
+ */
+ public get(handle: ImpulseJointHandle): ImpulseJoint | null {
+ return this.map.get(handle);
+ }
+
+ /**
+ * Applies the given closure to each joint contained by this set.
+ *
+ * @param f - The closure to apply.
+ */
+ public forEach(f: (joint: ImpulseJoint) => void) {
+ this.map.forEach(f);
+ }
+
+ /**
+ * Gets all joints in the list.
+ *
+ * @returns joint list.
+ */
+ public getAll(): ImpulseJoint[] {
+ return this.map.getAll();
+ }
+}
diff --git a/typescript/src.ts/dynamics/index.ts b/typescript/src.ts/dynamics/index.ts
new file mode 100644
index 000000000..4141658e9
--- /dev/null
+++ b/typescript/src.ts/dynamics/index.ts
@@ -0,0 +1,10 @@
+export * from "./rigid_body";
+export * from "./rigid_body_set";
+export * from "./integration_parameters";
+export * from "./impulse_joint";
+export * from "./impulse_joint_set";
+export * from "./multibody_joint";
+export * from "./multibody_joint_set";
+export * from "./coefficient_combine_rule";
+export * from "./ccd_solver";
+export * from "./island_manager";
diff --git a/typescript/src.ts/dynamics/integration_parameters.ts b/typescript/src.ts/dynamics/integration_parameters.ts
new file mode 100644
index 000000000..b7253e21a
--- /dev/null
+++ b/typescript/src.ts/dynamics/integration_parameters.ts
@@ -0,0 +1,126 @@
+import {RawIntegrationParameters} from "../raw";
+
+export class IntegrationParameters {
+ raw: RawIntegrationParameters;
+
+ constructor(raw?: RawIntegrationParameters) {
+ this.raw = raw || new RawIntegrationParameters();
+ }
+
+ /**
+ * Free the WASM memory used by these integration parameters.
+ */
+ public free() {
+ if (!!this.raw) {
+ this.raw.free();
+ }
+ this.raw = undefined;
+ }
+
+ /**
+ * The timestep length (default: `1.0 / 60.0`)
+ */
+ get dt(): number {
+ return this.raw.dt;
+ }
+
+ /**
+ * The Error Reduction Parameter in `[0, 1]` is the proportion of
+ * the positional error to be corrected at each time step (default: `0.2`).
+ */
+ get contact_erp(): number {
+ return this.raw.contact_erp;
+ }
+
+ get lengthUnit(): number {
+ return this.raw.lengthUnit;
+ }
+
+ /**
+ * Normalized amount of penetration the engine won’t attempt to correct (default: `0.001m`).
+ *
+ * This threshold considered by the physics engine is this value multiplied by the `lengthUnit`.
+ */
+ get normalizedAllowedLinearError(): number {
+ return this.raw.normalizedAllowedLinearError;
+ }
+
+ /**
+ * The maximal normalized distance separating two objects that will generate predictive contacts (default: `0.002`).
+ *
+ * This threshold considered by the physics engine is this value multiplied by the `lengthUnit`.
+ */
+ get normalizedPredictionDistance(): number {
+ return this.raw.normalizedPredictionDistance;
+ }
+
+ /**
+ * The number of solver iterations run by the constraints solver for calculating forces (default: `4`).
+ */
+ get numSolverIterations(): number {
+ return this.raw.numSolverIterations;
+ }
+
+ /**
+ * Number of internal Project Gauss Seidel (PGS) iterations run at each solver iteration (default: `1`).
+ */
+ get numInternalPgsIterations(): number {
+ return this.raw.numInternalPgsIterations;
+ }
+
+ /**
+ * Minimum number of dynamic bodies in each active island (default: `128`).
+ */
+ get minIslandSize(): number {
+ return this.raw.minIslandSize;
+ }
+
+ /**
+ * Maximum number of substeps performed by the solver (default: `1`).
+ */
+ get maxCcdSubsteps(): number {
+ return this.raw.maxCcdSubsteps;
+ }
+
+ set dt(value: number) {
+ this.raw.dt = value;
+ }
+
+ set contact_natural_frequency(value: number) {
+ this.raw.contact_natural_frequency = value;
+ }
+
+ set lengthUnit(value: number) {
+ this.raw.lengthUnit = value;
+ }
+
+ set normalizedAllowedLinearError(value: number) {
+ this.raw.normalizedAllowedLinearError = value;
+ }
+
+ set normalizedPredictionDistance(value: number) {
+ this.raw.normalizedPredictionDistance = value;
+ }
+
+ /**
+ * Sets the number of solver iterations run by the constraints solver for calculating forces (default: `4`).
+ */
+ set numSolverIterations(value: number) {
+ this.raw.numSolverIterations = value;
+ }
+
+ /**
+ * Sets the number of internal Project Gauss Seidel (PGS) iterations run at each solver iteration (default: `1`).
+ */
+ set numInternalPgsIterations(value: number) {
+ this.raw.numInternalPgsIterations = value;
+ }
+
+ set minIslandSize(value: number) {
+ this.raw.minIslandSize = value;
+ }
+
+ set maxCcdSubsteps(value: number) {
+ this.raw.maxCcdSubsteps = value;
+ }
+}
diff --git a/typescript/src.ts/dynamics/island_manager.ts b/typescript/src.ts/dynamics/island_manager.ts
new file mode 100644
index 000000000..65ed21dcb
--- /dev/null
+++ b/typescript/src.ts/dynamics/island_manager.ts
@@ -0,0 +1,37 @@
+import {RawIslandManager} from "../raw";
+import {RigidBodyHandle} from "./rigid_body";
+
+/**
+ * The CCD solver responsible for resolving Continuous Collision Detection.
+ *
+ * To avoid leaking WASM resources, this MUST be freed manually with `ccdSolver.free()`
+ * once you are done using it.
+ */
+export class IslandManager {
+ raw: RawIslandManager;
+
+ /**
+ * Release the WASM memory occupied by this narrow-phase.
+ */
+ public free() {
+ if (!!this.raw) {
+ this.raw.free();
+ }
+ this.raw = undefined;
+ }
+
+ constructor(raw?: RawIslandManager) {
+ this.raw = raw || new RawIslandManager();
+ }
+
+ /**
+ * Applies the given closure to the handle of each active rigid-bodies contained by this set.
+ *
+ * A rigid-body is active if it is not sleeping, i.e., if it moved recently.
+ *
+ * @param f - The closure to apply.
+ */
+ public forEachActiveRigidBodyHandle(f: (handle: RigidBodyHandle) => void) {
+ this.raw.forEachActiveRigidBodyHandle(f);
+ }
+}
diff --git a/typescript/src.ts/dynamics/multibody_joint.ts b/typescript/src.ts/dynamics/multibody_joint.ts
new file mode 100644
index 000000000..5608aec7f
--- /dev/null
+++ b/typescript/src.ts/dynamics/multibody_joint.ts
@@ -0,0 +1,222 @@
+import {
+ RawImpulseJointSet,
+ RawJointAxis,
+ RawJointType,
+ RawMultibodyJointSet,
+} from "../raw";
+import {
+ FixedImpulseJoint,
+ ImpulseJointHandle,
+ JointType,
+ MotorModel,
+ PrismaticImpulseJoint,
+ RevoluteImpulseJoint,
+} from "./impulse_joint";
+
+// #if DIM3
+import {Quaternion} from "../math";
+import {SphericalImpulseJoint} from "./impulse_joint";
+// #endif
+
+/**
+ * The integer identifier of a collider added to a `ColliderSet`.
+ */
+export type MultibodyJointHandle = number;
+
+export class MultibodyJoint {
+ protected rawSet: RawMultibodyJointSet; // The MultibodyJoint won't need to free this.
+ handle: MultibodyJointHandle;
+
+ constructor(rawSet: RawMultibodyJointSet, handle: MultibodyJointHandle) {
+ this.rawSet = rawSet;
+ this.handle = handle;
+ }
+
+ public static newTyped(
+ rawSet: RawMultibodyJointSet,
+ handle: MultibodyJointHandle,
+ ): MultibodyJoint {
+ switch (rawSet.jointType(handle)) {
+ case RawJointType.Revolute:
+ return new RevoluteMultibodyJoint(rawSet, handle);
+ case RawJointType.Prismatic:
+ return new PrismaticMultibodyJoint(rawSet, handle);
+ case RawJointType.Fixed:
+ return new FixedMultibodyJoint(rawSet, handle);
+ // #if DIM3
+ case RawJointType.Spherical:
+ return new SphericalMultibodyJoint(rawSet, handle);
+ // #endif
+ default:
+ return new MultibodyJoint(rawSet, handle);
+ }
+ }
+
+ /**
+ * Checks if this joint is still valid (i.e. that it has
+ * not been deleted from the joint set yet).
+ */
+ public isValid(): boolean {
+ return this.rawSet.contains(this.handle);
+ }
+
+ // /**
+ // * The unique integer identifier of the first rigid-body this joint it attached to.
+ // */
+ // public bodyHandle1(): RigidBodyHandle {
+ // return this.rawSet.jointBodyHandle1(this.handle);
+ // }
+ //
+ // /**
+ // * The unique integer identifier of the second rigid-body this joint is attached to.
+ // */
+ // public bodyHandle2(): RigidBodyHandle {
+ // return this.rawSet.jointBodyHandle2(this.handle);
+ // }
+ //
+ // /**
+ // * The type of this joint given as a string.
+ // */
+ // public type(): JointType {
+ // return this.rawSet.jointType(this.handle);
+ // }
+ //
+ // // #if DIM3
+ // /**
+ // * The rotation quaternion that aligns this joint's first local axis to the `x` axis.
+ // */
+ // public frameX1(): Rotation {
+ // return RotationOps.fromRaw(this.rawSet.jointFrameX1(this.handle));
+ // }
+ //
+ // // #endif
+ //
+ // // #if DIM3
+ // /**
+ // * The rotation matrix that aligns this joint's second local axis to the `x` axis.
+ // */
+ // public frameX2(): Rotation {
+ // return RotationOps.fromRaw(this.rawSet.jointFrameX2(this.handle));
+ // }
+ //
+ // // #endif
+ //
+ // /**
+ // * The position of the first anchor of this joint.
+ // *
+ // * The first anchor gives the position of the points application point on the
+ // * local frame of the first rigid-body it is attached to.
+ // */
+ // public anchor1(): Vector {
+ // return VectorOps.fromRaw(this.rawSet.jointAnchor1(this.handle));
+ // }
+ //
+ // /**
+ // * The position of the second anchor of this joint.
+ // *
+ // * The second anchor gives the position of the points application point on the
+ // * local frame of the second rigid-body it is attached to.
+ // */
+ // public anchor2(): Vector {
+ // return VectorOps.fromRaw(this.rawSet.jointAnchor2(this.handle));
+ // }
+
+ /**
+ * Controls whether contacts are computed between colliders attached
+ * to the rigid-bodies linked by this joint.
+ */
+ public setContactsEnabled(enabled: boolean) {
+ this.rawSet.jointSetContactsEnabled(this.handle, enabled);
+ }
+
+ /**
+ * Indicates if contacts are enabled between colliders attached
+ * to the rigid-bodies linked by this joint.
+ */
+ public contactsEnabled(): boolean {
+ return this.rawSet.jointContactsEnabled(this.handle);
+ }
+}
+
+export class UnitMultibodyJoint extends MultibodyJoint {
+ /**
+ * The axis left free by this joint.
+ */
+ protected rawAxis?(): RawJointAxis;
+
+ // /**
+ // * Are the limits enabled for this joint?
+ // */
+ // public limitsEnabled(): boolean {
+ // return this.rawSet.jointLimitsEnabled(this.handle, this.rawAxis());
+ // }
+ //
+ // /**
+ // * The min limit of this joint.
+ // */
+ // public limitsMin(): number {
+ // return this.rawSet.jointLimitsMin(this.handle, this.rawAxis());
+ // }
+ //
+ // /**
+ // * The max limit of this joint.
+ // */
+ // public limitsMax(): number {
+ // return this.rawSet.jointLimitsMax(this.handle, this.rawAxis());
+ // }
+ //
+ // public configureMotorModel(model: MotorModel) {
+ // this.rawSet.jointConfigureMotorModel(this.handle, this.rawAxis(), model);
+ // }
+ //
+ // public configureMotorVelocity(targetVel: number, factor: number) {
+ // this.rawSet.jointConfigureMotorVelocity(this.handle, this.rawAxis(), targetVel, factor);
+ // }
+ //
+ // public configureMotorPosition(targetPos: number, stiffness: number, damping: number) {
+ // this.rawSet.jointConfigureMotorPosition(this.handle, this.rawAxis(), targetPos, stiffness, damping);
+ // }
+ //
+ // public configureMotor(targetPos: number, targetVel: number, stiffness: number, damping: number) {
+ // this.rawSet.jointConfigureMotor(this.handle, this.rawAxis(), targetPos, targetVel, stiffness, damping);
+ // }
+}
+
+export class FixedMultibodyJoint extends MultibodyJoint {}
+
+export class PrismaticMultibodyJoint extends UnitMultibodyJoint {
+ public rawAxis(): RawJointAxis {
+ return RawJointAxis.LinX;
+ }
+}
+
+export class RevoluteMultibodyJoint extends UnitMultibodyJoint {
+ public rawAxis(): RawJointAxis {
+ return RawJointAxis.AngX;
+ }
+}
+
+// #if DIM3
+export class SphericalMultibodyJoint extends MultibodyJoint {
+ /* Unsupported by this alpha release.
+ public configureMotorModel(model: MotorModel) {
+ this.rawSet.jointConfigureMotorModel(this.handle, model);
+ }
+
+ public configureMotorVelocity(targetVel: Vector, factor: number) {
+ this.rawSet.jointConfigureBallMotorVelocity(this.handle, targetVel.x, targetVel.y, targetVel.z, factor);
+ }
+
+ public configureMotorPosition(targetPos: Quaternion, stiffness: number, damping: number) {
+ this.rawSet.jointConfigureBallMotorPosition(this.handle, targetPos.w, targetPos.x, targetPos.y, targetPos.z, stiffness, damping);
+ }
+
+ public configureMotor(targetPos: Quaternion, targetVel: Vector, stiffness: number, damping: number) {
+ this.rawSet.jointConfigureBallMotor(this.handle,
+ targetPos.w, targetPos.x, targetPos.y, targetPos.z,
+ targetVel.x, targetVel.y, targetVel.z,
+ stiffness, damping);
+ }
+ */
+}
+// #endif
diff --git a/typescript/src.ts/dynamics/multibody_joint_set.ts b/typescript/src.ts/dynamics/multibody_joint_set.ts
new file mode 100644
index 000000000..2fbb34030
--- /dev/null
+++ b/typescript/src.ts/dynamics/multibody_joint_set.ts
@@ -0,0 +1,157 @@
+import {RawMultibodyJointSet} from "../raw";
+import {Coarena} from "../coarena";
+import {RigidBodySet} from "./rigid_body_set";
+import {
+ MultibodyJoint,
+ MultibodyJointHandle,
+ RevoluteMultibodyJoint,
+ FixedMultibodyJoint,
+ PrismaticMultibodyJoint,
+ // #if DIM3
+ SphericalMultibodyJoint,
+ // #endif
+} from "./multibody_joint";
+import {ImpulseJointHandle, JointData, JointType} from "./impulse_joint";
+import {IslandManager} from "./island_manager";
+import {ColliderHandle} from "../geometry";
+import {RigidBodyHandle} from "./rigid_body";
+
+/**
+ * A set of joints.
+ *
+ * To avoid leaking WASM resources, this MUST be freed manually with `jointSet.free()`
+ * once you are done using it (and all the joints it created).
+ */
+export class MultibodyJointSet {
+ raw: RawMultibodyJointSet;
+ private map: Coarena;
+
+ /**
+ * Release the WASM memory occupied by this joint set.
+ */
+ public free() {
+ if (!!this.raw) {
+ this.raw.free();
+ }
+ this.raw = undefined;
+
+ if (!!this.map) {
+ this.map.clear();
+ }
+ this.map = undefined;
+ }
+
+ constructor(raw?: RawMultibodyJointSet) {
+ this.raw = raw || new RawMultibodyJointSet();
+ this.map = new Coarena();
+ // Initialize the map with the existing elements, if any.
+ if (raw) {
+ raw.forEachJointHandle((handle: MultibodyJointHandle) => {
+ this.map.set(handle, MultibodyJoint.newTyped(this.raw, handle));
+ });
+ }
+ }
+
+ /**
+ * Creates a new joint and return its integer handle.
+ *
+ * @param desc - The joint's parameters.
+ * @param parent1 - The handle of the first rigid-body this joint is attached to.
+ * @param parent2 - The handle of the second rigid-body this joint is attached to.
+ * @param wakeUp - Should the attached rigid-bodies be awakened?
+ */
+ public createJoint(
+ desc: JointData,
+ parent1: RigidBodyHandle,
+ parent2: RigidBodyHandle,
+ wakeUp: boolean,
+ ): MultibodyJoint {
+ const rawParams = desc.intoRaw();
+ const handle = this.raw.createJoint(
+ rawParams,
+ parent1,
+ parent2,
+ wakeUp,
+ );
+ rawParams.free();
+ let joint = MultibodyJoint.newTyped(this.raw, handle);
+ this.map.set(handle, joint);
+ return joint;
+ }
+
+ /**
+ * Remove a joint from this set.
+ *
+ * @param handle - The integer handle of the joint.
+ * @param wake_up - If `true`, the rigid-bodies attached by the removed joint will be woken-up automatically.
+ */
+ public remove(handle: MultibodyJointHandle, wake_up: boolean) {
+ this.raw.remove(handle, wake_up);
+ this.map.delete(handle);
+ }
+
+ /**
+ * Internal function, do not call directly.
+ * @param handle
+ */
+ public unmap(handle: MultibodyJointHandle) {
+ this.map.delete(handle);
+ }
+
+ /**
+ * The number of joints on this set.
+ */
+ public len(): number {
+ return this.map.len();
+ }
+
+ /**
+ * Does this set contain a joint with the given handle?
+ *
+ * @param handle - The joint handle to check.
+ */
+ public contains(handle: MultibodyJointHandle): boolean {
+ return this.get(handle) != null;
+ }
+
+ /**
+ * Gets the joint with the given handle.
+ *
+ * Returns `null` if no joint with the specified handle exists.
+ *
+ * @param handle - The integer handle of the joint to retrieve.
+ */
+ public get(handle: MultibodyJointHandle): MultibodyJoint | null {
+ return this.map.get(handle);
+ }
+
+ /**
+ * Applies the given closure to each joint contained by this set.
+ *
+ * @param f - The closure to apply.
+ */
+ public forEach(f: (joint: MultibodyJoint) => void) {
+ this.map.forEach(f);
+ }
+
+ /**
+ * Calls the given closure with the integer handle of each multibody joint attached to this rigid-body.
+ *
+ * @param f - The closure called with the integer handle of each multibody joint attached to the rigid-body.
+ */
+ public forEachJointHandleAttachedToRigidBody(
+ handle: RigidBodyHandle,
+ f: (handle: MultibodyJointHandle) => void,
+ ) {
+ this.raw.forEachJointAttachedToRigidBody(handle, f);
+ }
+
+ /**
+ * Gets all joints in the list.
+ *
+ * @returns joint list.
+ */
+ public getAll(): MultibodyJoint[] {
+ return this.map.getAll();
+ }
+}
diff --git a/typescript/src.ts/dynamics/rigid_body.ts b/typescript/src.ts/dynamics/rigid_body.ts
new file mode 100644
index 000000000..8363f3754
--- /dev/null
+++ b/typescript/src.ts/dynamics/rigid_body.ts
@@ -0,0 +1,1762 @@
+import {RawRigidBodySet, RawRigidBodyType} from "../raw";
+import {Rotation, RotationOps, Vector, VectorOps, scratchBuffer} from "../math";
+// #if DIM3
+import {SdpMatrix3, SdpMatrix3Ops} from "../math";
+// #endif
+import {Collider, ColliderSet} from "../geometry";
+
+/**
+ * The integer identifier of a collider added to a `ColliderSet`.
+ */
+export type RigidBodyHandle = number;
+
+/**
+ * The simulation status of a rigid-body.
+ */
+// TODO: rename this to RigidBodyType
+export enum RigidBodyType {
+ /**
+ * A `RigidBodyType::Dynamic` body can be affected by all external forces.
+ */
+ Dynamic = 0,
+ /**
+ * A `RigidBodyType::Fixed` body cannot be affected by external forces.
+ */
+ Fixed,
+ /**
+ * A `RigidBodyType::KinematicPositionBased` body cannot be affected by any external forces but can be controlled
+ * by the user at the position level while keeping realistic one-way interaction with dynamic bodies.
+ *
+ * One-way interaction means that a kinematic body can push a dynamic body, but a kinematic body
+ * cannot be pushed by anything. In other words, the trajectory of a kinematic body can only be
+ * modified by the user and is independent from any contact or joint it is involved in.
+ */
+ KinematicPositionBased,
+ /**
+ * A `RigidBodyType::KinematicVelocityBased` body cannot be affected by any external forces but can be controlled
+ * by the user at the velocity level while keeping realistic one-way interaction with dynamic bodies.
+ *
+ * One-way interaction means that a kinematic body can push a dynamic body, but a kinematic body
+ * cannot be pushed by anything. In other words, the trajectory of a kinematic body can only be
+ * modified by the user and is independent from any contact or joint it is involved in.
+ */
+ KinematicVelocityBased,
+}
+
+/**
+ * A rigid-body.
+ */
+export class RigidBody {
+ private rawSet: RawRigidBodySet; // The RigidBody won't need to free this.
+ private colliderSet: ColliderSet;
+ readonly handle: RigidBodyHandle;
+
+ /**
+ * An arbitrary user-defined object associated with this rigid-body.
+ */
+ public userData?: unknown;
+
+ constructor(
+ rawSet: RawRigidBodySet,
+ colliderSet: ColliderSet,
+ handle: RigidBodyHandle,
+ ) {
+ this.rawSet = rawSet;
+ this.colliderSet = colliderSet;
+ this.handle = handle;
+ }
+
+ /** @internal */
+ public finalizeDeserialization(colliderSet: ColliderSet) {
+ this.colliderSet = colliderSet;
+ }
+
+ /**
+ * Checks if this rigid-body is still valid (i.e. that it has
+ * not been deleted from the rigid-body set yet.
+ */
+ public isValid(): boolean {
+ return this.rawSet.contains(this.handle);
+ }
+
+ /**
+ * Locks or unlocks the ability of this rigid-body to translate.
+ *
+ * @param locked - If `true`, this rigid-body will no longer translate due to forces and impulses.
+ * @param wakeUp - If `true`, this rigid-body will be automatically awaken if it is currently asleep.
+ */
+ public lockTranslations(locked: boolean, wakeUp: boolean) {
+ return this.rawSet.rbLockTranslations(this.handle, locked, wakeUp);
+ }
+
+ /**
+ * Locks or unlocks the ability of this rigid-body to rotate.
+ *
+ * @param locked - If `true`, this rigid-body will no longer rotate due to torques and impulses.
+ * @param wakeUp - If `true`, this rigid-body will be automatically awaken if it is currently asleep.
+ */
+ public lockRotations(locked: boolean, wakeUp: boolean) {
+ return this.rawSet.rbLockRotations(this.handle, locked, wakeUp);
+ }
+
+ // #if DIM2
+ /**
+ * Locks or unlocks the ability of this rigid-body to translation along individual coordinate axes.
+ *
+ * @param enableX - If `false`, this rigid-body will no longer rotate due to torques and impulses, along the X coordinate axis.
+ * @param enableY - If `false`, this rigid-body will no longer rotate due to torques and impulses, along the Y coordinate axis.
+ * @param wakeUp - If `true`, this rigid-body will be automatically awaken if it is currently asleep.
+ */
+ public setEnabledTranslations(
+ enableX: boolean,
+ enableY: boolean,
+ wakeUp: boolean,
+ ) {
+ return this.rawSet.rbSetEnabledTranslations(
+ this.handle,
+ enableX,
+ enableY,
+ wakeUp,
+ );
+ }
+
+ /**
+ * Locks or unlocks the ability of this rigid-body to translation along individual coordinate axes.
+ *
+ * @param enableX - If `false`, this rigid-body will no longer rotate due to torques and impulses, along the X coordinate axis.
+ * @param enableY - If `false`, this rigid-body will no longer rotate due to torques and impulses, along the Y coordinate axis.
+ * @param wakeUp - If `true`, this rigid-body will be automatically awaken if it is currently asleep.
+ * @deprecated use `this.setEnabledTranslations` with the same arguments instead.
+ */
+ public restrictTranslations(
+ enableX: boolean,
+ enableY: boolean,
+ wakeUp: boolean,
+ ) {
+ this.setEnabledTranslations(enableX, enableX, wakeUp);
+ }
+
+ // #endif
+ // #if DIM3
+ /**
+ * Locks or unlocks the ability of this rigid-body to translate along individual coordinate axes.
+ *
+ * @param enableX - If `false`, this rigid-body will no longer translate due to torques and impulses, along the X coordinate axis.
+ * @param enableY - If `false`, this rigid-body will no longer translate due to torques and impulses, along the Y coordinate axis.
+ * @param enableZ - If `false`, this rigid-body will no longer translate due to torques and impulses, along the Z coordinate axis.
+ * @param wakeUp - If `true`, this rigid-body will be automatically awaken if it is currently asleep.
+ */
+ public setEnabledTranslations(
+ enableX: boolean,
+ enableY: boolean,
+ enableZ: boolean,
+ wakeUp: boolean,
+ ) {
+ return this.rawSet.rbSetEnabledTranslations(
+ this.handle,
+ enableX,
+ enableY,
+ enableZ,
+ wakeUp,
+ );
+ }
+
+ /**
+ * Locks or unlocks the ability of this rigid-body to translate along individual coordinate axes.
+ *
+ * @param enableX - If `false`, this rigid-body will no longer translate due to torques and impulses, along the X coordinate axis.
+ * @param enableY - If `false`, this rigid-body will no longer translate due to torques and impulses, along the Y coordinate axis.
+ * @param enableZ - If `false`, this rigid-body will no longer translate due to torques and impulses, along the Z coordinate axis.
+ * @param wakeUp - If `true`, this rigid-body will be automatically awaken if it is currently asleep.
+ * @deprecated use `this.setEnabledTranslations` with the same arguments instead.
+ */
+ public restrictTranslations(
+ enableX: boolean,
+ enableY: boolean,
+ enableZ: boolean,
+ wakeUp: boolean,
+ ) {
+ this.setEnabledTranslations(enableX, enableY, enableZ, wakeUp);
+ }
+
+ /**
+ * Locks or unlocks the ability of this rigid-body to rotate along individual coordinate axes.
+ *
+ * @param enableX - If `false`, this rigid-body will no longer rotate due to torques and impulses, along the X coordinate axis.
+ * @param enableY - If `false`, this rigid-body will no longer rotate due to torques and impulses, along the Y coordinate axis.
+ * @param enableZ - If `false`, this rigid-body will no longer rotate due to torques and impulses, along the Z coordinate axis.
+ * @param wakeUp - If `true`, this rigid-body will be automatically awaken if it is currently asleep.
+ */
+ public setEnabledRotations(
+ enableX: boolean,
+ enableY: boolean,
+ enableZ: boolean,
+ wakeUp: boolean,
+ ) {
+ return this.rawSet.rbSetEnabledRotations(
+ this.handle,
+ enableX,
+ enableY,
+ enableZ,
+ wakeUp,
+ );
+ }
+
+ /**
+ * Locks or unlocks the ability of this rigid-body to rotate along individual coordinate axes.
+ *
+ * @param enableX - If `false`, this rigid-body will no longer rotate due to torques and impulses, along the X coordinate axis.
+ * @param enableY - If `false`, this rigid-body will no longer rotate due to torques and impulses, along the Y coordinate axis.
+ * @param enableZ - If `false`, this rigid-body will no longer rotate due to torques and impulses, along the Z coordinate axis.
+ * @param wakeUp - If `true`, this rigid-body will be automatically awaken if it is currently asleep.
+ * @deprecated use `this.setEnabledRotations` with the same arguments instead.
+ */
+ public restrictRotations(
+ enableX: boolean,
+ enableY: boolean,
+ enableZ: boolean,
+ wakeUp: boolean,
+ ) {
+ this.setEnabledRotations(enableX, enableY, enableZ, wakeUp);
+ }
+
+ // #endif
+
+ /**
+ * The dominance group, in [-127, +127] this rigid-body is part of.
+ */
+ public dominanceGroup(): number {
+ return this.rawSet.rbDominanceGroup(this.handle);
+ }
+
+ /**
+ * Sets the dominance group of this rigid-body.
+ *
+ * @param group - The dominance group of this rigid-body. Must be a signed integer in the range [-127, +127].
+ */
+ public setDominanceGroup(group: number) {
+ this.rawSet.rbSetDominanceGroup(this.handle, group);
+ }
+
+ /**
+ * The number of additional solver iterations that will be run for this
+ * rigid-body and everything that interacts with it directly or indirectly
+ * through contacts or joints.
+ */
+ public additionalSolverIterations(): number {
+ return this.rawSet.rbAdditionalSolverIterations(this.handle);
+ }
+
+ /**
+ * Sets the number of additional solver iterations that will be run for this
+ * rigid-body and everything that interacts with it directly or indirectly
+ * through contacts or joints.
+ *
+ * Compared to increasing the global `World.numSolverIteration`, setting this
+ * value lets you increase accuracy on only a subset of the scene, resulting in reduced
+ * performance loss.
+ *
+ * @param iters - The new number of additional solver iterations (default: 0).
+ */
+ public setAdditionalSolverIterations(iters: number) {
+ this.rawSet.rbSetAdditionalSolverIterations(this.handle, iters);
+ }
+
+ /**
+ * Enable or disable CCD (Continuous Collision Detection) for this rigid-body.
+ *
+ * @param enabled - If `true`, CCD will be enabled for this rigid-body.
+ */
+ public enableCcd(enabled: boolean) {
+ this.rawSet.rbEnableCcd(this.handle, enabled);
+ }
+
+ /**
+ * Sets the soft-CCD prediction distance for this rigid-body.
+ *
+ * See the documentation of `RigidBodyDesc.setSoftCcdPrediction` for
+ * additional details.
+ */
+ public setSoftCcdPrediction(distance: number) {
+ this.rawSet.rbSetSoftCcdPrediction(this.handle, distance);
+ }
+
+ /**
+ * Gets the soft-CCD prediction distance for this rigid-body.
+ *
+ * See the documentation of `RigidBodyDesc.setSoftCcdPrediction` for
+ * additional details.
+ */
+ public softCcdPrediction(): number {
+ return this.rawSet.rbSoftCcdPrediction(this.handle);
+ }
+
+ /**
+ * The world-space translation of this rigid-body.
+ *
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public translation(target?: Vector): Vector {
+ this.rawSet.rbTranslation(this.handle, scratchBuffer);
+ return VectorOps.fromBuffer(scratchBuffer, target);
+ }
+
+ // #if DIM2
+ /**
+ * The world-space orientation of this rigid-body.
+ */
+ public rotation(): number {
+ return this.rawSet.rbRotation(this.handle);
+ }
+ // #endif
+
+ // #if DIM3
+ /**
+ * The world-space orientation of this rigid-body.
+ *
+ * @param {Rotation?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public rotation(target?: Rotation): Rotation {
+ this.rawSet.rbRotation(this.handle, scratchBuffer);
+ return RotationOps.fromBuffer(scratchBuffer, target);
+ }
+ // #endif
+
+ /**
+ * The world-space next translation of this rigid-body.
+ *
+ * If this rigid-body is kinematic this value is set by the `setNextKinematicTranslation`
+ * method and is used for estimating the kinematic body velocity at the next timestep.
+ * For non-kinematic bodies, this value is currently unspecified.
+ *
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public nextTranslation(target?: Vector): Vector {
+ this.rawSet.rbNextTranslation(this.handle, scratchBuffer);
+ return VectorOps.fromBuffer(scratchBuffer, target);
+ }
+
+ // #if DIM2
+ /**
+ * The world-space next orientation of this rigid-body.
+ *
+ * If this rigid-body is kinematic this value is set by the `setNextKinematicRotation`
+ * method and is used for estimating the kinematic body velocity at the next timestep.
+ * For non-kinematic bodies, this value is currently unspecified.
+ */
+ public nextRotation(): number {
+ return this.rawSet.rbNextRotation(this.handle);
+ }
+ // #endif
+
+ // #if DIM3
+ /**
+ * The world-space next orientation of this rigid-body.
+ *
+ * If this rigid-body is kinematic this value is set by the `setNextKinematicRotation`
+ * method and is used for estimating the kinematic body velocity at the next timestep.
+ * For non-kinematic bodies, this value is currently unspecified.
+ *
+ * @param {Rotation?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public nextRotation(target?: Rotation): Rotation {
+ this.rawSet.rbNextRotation(this.handle, scratchBuffer);
+ return RotationOps.fromBuffer(scratchBuffer, target);
+ }
+ // #endif
+
+ /**
+ * Sets the translation of this rigid-body.
+ *
+ * @param tra - The world-space position of the rigid-body.
+ * @param wakeUp - Forces the rigid-body to wake-up so it is properly affected by forces if it
+ * wasn't moving before modifying its position.
+ */
+ public setTranslation(tra: Vector, wakeUp: boolean) {
+ // #if DIM2
+ this.rawSet.rbSetTranslation(this.handle, tra.x, tra.y, wakeUp);
+ // #endif
+ // #if DIM3
+ this.rawSet.rbSetTranslation(this.handle, tra.x, tra.y, tra.z, wakeUp);
+ // #endif
+ }
+
+ /**
+ * Sets the linear velocity of this rigid-body.
+ *
+ * @param vel - The linear velocity to set.
+ * @param wakeUp - Forces the rigid-body to wake-up if it was asleep.
+ */
+ public setLinvel(vel: Vector, wakeUp: boolean) {
+ let rawVel = VectorOps.intoRaw(vel);
+ this.rawSet.rbSetLinvel(this.handle, rawVel, wakeUp);
+ rawVel.free();
+ }
+
+ /**
+ * The scale factor applied to the gravity affecting
+ * this rigid-body.
+ */
+ public gravityScale(): number {
+ return this.rawSet.rbGravityScale(this.handle);
+ }
+
+ /**
+ * Sets the scale factor applied to the gravity affecting
+ * this rigid-body.
+ *
+ * @param factor - The scale factor to set. A value of 0.0 means
+ * that this rigid-body will on longer be affected by gravity.
+ * @param wakeUp - Forces the rigid-body to wake-up if it was asleep.
+ */
+ public setGravityScale(factor: number, wakeUp: boolean) {
+ this.rawSet.rbSetGravityScale(this.handle, factor, wakeUp);
+ }
+
+ // #if DIM3
+ /**
+ * Sets the rotation quaternion of this rigid-body.
+ *
+ * This does nothing if a zero quaternion is provided.
+ *
+ * @param rotation - The rotation to set.
+ * @param wakeUp - Forces the rigid-body to wake-up so it is properly affected by forces if it
+ * wasn't moving before modifying its position.
+ */
+ public setRotation(rot: Rotation, wakeUp: boolean) {
+ this.rawSet.rbSetRotation(
+ this.handle,
+ rot.x,
+ rot.y,
+ rot.z,
+ rot.w,
+ wakeUp,
+ );
+ }
+
+ /**
+ * Sets the angular velocity for this rigid-body.
+ *
+ * @param vel - The angular velocity to set.
+ * @param wakeUp - Forces the rigid-body to wake-up if it was asleep.
+ */
+ public setAngvel(vel: Vector, wakeUp: boolean) {
+ let rawVel = VectorOps.intoRaw(vel);
+ this.rawSet.rbSetAngvel(this.handle, rawVel, wakeUp);
+ rawVel.free();
+ }
+
+ // #endif
+
+ // #if DIM2
+ /**
+ * Sets the rotation angle of this rigid-body.
+ *
+ * @param angle - The rotation angle, in radians.
+ * @param wakeUp - Forces the rigid-body to wake-up so it is properly affected by forces if it
+ * wasn't moving before modifying its position.
+ */
+ public setRotation(angle: number, wakeUp: boolean) {
+ this.rawSet.rbSetRotation(this.handle, angle, wakeUp);
+ }
+
+ /**
+ * Sets the angular velocity for this rigid-body.
+ *
+ * @param vel - The angular velocity to set.
+ * @param wakeUp - Forces the rigid-body to wake-up if it was asleep.
+ */
+ public setAngvel(vel: number, wakeUp: boolean) {
+ this.rawSet.rbSetAngvel(this.handle, vel, wakeUp);
+ }
+
+ // #endif
+
+ /**
+ * If this rigid body is kinematic, sets its future translation after the next timestep integration.
+ *
+ * This should be used instead of `rigidBody.setTranslation` to make the dynamic object
+ * interacting with this kinematic body behave as expected. Internally, Rapier will compute
+ * an artificial velocity for this rigid-body from its current position and its next kinematic
+ * position. This velocity will be used to compute forces on dynamic bodies interacting with
+ * this body.
+ *
+ * @param t - The kinematic translation to set.
+ */
+ public setNextKinematicTranslation(t: Vector) {
+ // #if DIM2
+ this.rawSet.rbSetNextKinematicTranslation(this.handle, t.x, t.y);
+ // #endif
+ // #if DIM3
+ this.rawSet.rbSetNextKinematicTranslation(this.handle, t.x, t.y, t.z);
+ // #endif
+ }
+
+ // #if DIM3
+ /**
+ * If this rigid body is kinematic, sets its future rotation after the next timestep integration.
+ *
+ * This should be used instead of `rigidBody.setRotation` to make the dynamic object
+ * interacting with this kinematic body behave as expected. Internally, Rapier will compute
+ * an artificial velocity for this rigid-body from its current position and its next kinematic
+ * position. This velocity will be used to compute forces on dynamic bodies interacting with
+ * this body.
+ *
+ * @param rot - The kinematic rotation to set.
+ */
+ public setNextKinematicRotation(rot: Rotation) {
+ this.rawSet.rbSetNextKinematicRotation(
+ this.handle,
+ rot.x,
+ rot.y,
+ rot.z,
+ rot.w,
+ );
+ }
+
+ // #endif
+
+ // #if DIM2
+ /**
+ * If this rigid body is kinematic, sets its future rotation after the next timestep integration.
+ *
+ * This should be used instead of `rigidBody.setRotation` to make the dynamic object
+ * interacting with this kinematic body behave as expected. Internally, Rapier will compute
+ * an artificial velocity for this rigid-body from its current position and its next kinematic
+ * position. This velocity will be used to compute forces on dynamic bodies interacting with
+ * this body.
+ *
+ * @param angle - The kinematic rotation angle, in radians.
+ */
+ public setNextKinematicRotation(angle: number) {
+ this.rawSet.rbSetNextKinematicRotation(this.handle, angle);
+ }
+
+ // #endif
+
+ /**
+ * The linear velocity of this rigid-body.
+ *
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public linvel(target?: Vector): Vector {
+ this.rawSet.rbLinvel(this.handle, scratchBuffer);
+ return VectorOps.fromBuffer(scratchBuffer, target);
+ }
+
+ /**
+ * The velocity of the given world-space point on this rigid-body.
+ *
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public velocityAtPoint(point: Vector, target?: Vector): Vector {
+ const rawPoint = VectorOps.intoRaw(point);
+ this.rawSet.rbVelocityAtPoint(this.handle, rawPoint, scratchBuffer);
+ rawPoint.free();
+ return VectorOps.fromBuffer(scratchBuffer, target);
+ }
+
+ // #if DIM3
+ /**
+ * The angular velocity of this rigid-body.
+ *
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public angvel(target?: Vector): Vector {
+ this.rawSet.rbAngvel(this.handle, scratchBuffer);
+ return VectorOps.fromBuffer(scratchBuffer, target);
+ }
+ // #endif
+
+ // #if DIM2
+ /**
+ * The angular velocity of this rigid-body.
+ */
+ public angvel(): number {
+ return this.rawSet.rbAngvel(this.handle);
+ }
+ // #endif
+
+ /**
+ * The mass of this rigid-body.
+ */
+ public mass(): number {
+ return this.rawSet.rbMass(this.handle);
+ }
+
+ /**
+ * The inverse mass taking into account translation locking.
+ *
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public effectiveInvMass(target?: Vector): Vector {
+ this.rawSet.rbEffectiveInvMass(this.handle, scratchBuffer);
+ return VectorOps.fromBuffer(scratchBuffer, target);
+ }
+
+ /**
+ * The inverse of the mass of a rigid-body.
+ *
+ * If this is zero, the rigid-body is assumed to have infinite mass.
+ */
+ public invMass(): number {
+ return this.rawSet.rbInvMass(this.handle);
+ }
+
+ /**
+ * The center of mass of a rigid-body expressed in its local-space.
+ *
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public localCom(target?: Vector): Vector {
+ this.rawSet.rbLocalCom(this.handle, scratchBuffer);
+ return VectorOps.fromBuffer(scratchBuffer, target);
+ }
+
+ /**
+ * The world-space center of mass of the rigid-body.
+ *
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public worldCom(target?: Vector): Vector {
+ this.rawSet.rbWorldCom(this.handle, scratchBuffer);
+ return VectorOps.fromBuffer(scratchBuffer, target);
+ }
+
+ // #if DIM2
+ /**
+ * The inverse of the principal angular inertia of the rigid-body.
+ *
+ * Components set to zero are assumed to be infinite along the corresponding principal axis.
+ */
+ public invPrincipalInertia(): number {
+ return this.rawSet.rbInvPrincipalInertia(this.handle);
+ }
+ // #endif
+
+ // #if DIM3
+ /**
+ * The inverse of the principal angular inertia of the rigid-body.
+ *
+ * Components set to zero are assumed to be infinite along the corresponding principal axis.
+ *
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public invPrincipalInertia(target?: Vector): Vector {
+ this.rawSet.rbInvPrincipalInertia(this.handle, scratchBuffer);
+ return VectorOps.fromBuffer(scratchBuffer, target);
+ }
+ // #endif
+
+ // #if DIM2
+ /**
+ * The angular inertia along the principal inertia axes of the rigid-body.
+ */
+ public principalInertia(): number {
+ return this.rawSet.rbPrincipalInertia(this.handle);
+ }
+ // #endif
+
+ // #if DIM3
+ /**
+ * The angular inertia along the principal inertia axes of the rigid-body.
+ *
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public principalInertia(target?: Vector): Vector {
+ this.rawSet.rbPrincipalInertia(this.handle, scratchBuffer);
+ return VectorOps.fromBuffer(scratchBuffer, target);
+ }
+ // #endif
+
+ // #if DIM3
+ /**
+ * The principal vectors of the local angular inertia tensor of the rigid-body.
+ *
+ * @param {Rotation?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public principalInertiaLocalFrame(target?: Rotation): Rotation {
+ this.rawSet.rbPrincipalInertiaLocalFrame(this.handle, scratchBuffer);
+ return RotationOps.fromBuffer(scratchBuffer, target);
+ }
+ // #endif
+
+ // #if DIM2
+ /**
+ * The world-space inverse angular inertia tensor of the rigid-body,
+ * taking into account rotation locking.
+ */
+ public effectiveWorldInvInertia(): number {
+ return this.rawSet.rbEffectiveWorldInvInertia(this.handle);
+ }
+ // #endif
+
+ // #if DIM3
+ /**
+ * The world-space inverse angular inertia tensor of the rigid-body,
+ * taking into account rotation locking.
+ *
+ * @param {SdpMatrix3?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public effectiveWorldInvInertia(target?: SdpMatrix3): SdpMatrix3 {
+ this.rawSet.rbEffectiveWorldInvInertia(this.handle, scratchBuffer);
+ return SdpMatrix3Ops.fromBuffer(scratchBuffer, target);
+ }
+
+ // #endif
+
+ // #if DIM2
+ /**
+ * The effective world-space angular inertia (that takes the potential rotation locking into account) of
+ * this rigid-body.
+ */
+ public effectiveAngularInertia(): number {
+ return this.rawSet.rbEffectiveAngularInertia(this.handle);
+ }
+
+ // #endif
+
+ // #if DIM3
+ /**
+ * The effective world-space angular inertia (that takes the potential rotation locking into account) of
+ * this rigid-body.
+ *
+ * @param {SdpMatrix3?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public effectiveAngularInertia(target?: SdpMatrix3): SdpMatrix3 {
+ this.rawSet.rbEffectiveAngularInertia(this.handle, scratchBuffer);
+ return SdpMatrix3Ops.fromBuffer(scratchBuffer, target);
+ }
+
+ // #endif
+
+ /**
+ * Put this rigid body to sleep.
+ *
+ * A sleeping body no longer moves and is no longer simulated by the physics engine unless
+ * it is waken up. It can be woken manually with `this.wakeUp()` or automatically due to
+ * external forces like contacts.
+ */
+ public sleep() {
+ this.rawSet.rbSleep(this.handle);
+ }
+
+ /**
+ * Wakes this rigid-body up.
+ *
+ * A dynamic rigid-body that does not move during several consecutive frames will
+ * be put to sleep by the physics engine, i.e., it will stop being simulated in order
+ * to avoid useless computations.
+ * This methods forces a sleeping rigid-body to wake-up. This is useful, e.g., before modifying
+ * the position of a dynamic body so that it is properly simulated afterwards.
+ */
+ public wakeUp() {
+ this.rawSet.rbWakeUp(this.handle);
+ }
+
+ /**
+ * Is CCD enabled for this rigid-body?
+ */
+ public isCcdEnabled(): boolean {
+ return this.rawSet.rbIsCcdEnabled(this.handle);
+ }
+
+ /**
+ * The number of colliders attached to this rigid-body.
+ */
+ public numColliders(): number {
+ return this.rawSet.rbNumColliders(this.handle);
+ }
+
+ /**
+ * Retrieves the `i-th` collider attached to this rigid-body.
+ *
+ * @param i - The index of the collider to retrieve. Must be a number in `[0, this.numColliders()[`.
+ * This index is **not** the same as the unique identifier of the collider.
+ */
+ public collider(i: number): Collider {
+ return this.colliderSet.get(this.rawSet.rbCollider(this.handle, i));
+ }
+
+ /**
+ * Sets whether this rigid-body is enabled or not.
+ *
+ * @param enabled - Set to `false` to disable this rigid-body and all its attached colliders.
+ */
+ public setEnabled(enabled: boolean) {
+ this.rawSet.rbSetEnabled(this.handle, enabled);
+ }
+
+ /**
+ * Is this rigid-body enabled?
+ */
+ public isEnabled(): boolean {
+ return this.rawSet.rbIsEnabled(this.handle);
+ }
+
+ /**
+ * The status of this rigid-body: static, dynamic, or kinematic.
+ */
+ public bodyType(): RigidBodyType {
+ return this.rawSet.rbBodyType(this.handle) as number as RigidBodyType;
+ }
+
+ /**
+ * Set a new status for this rigid-body: static, dynamic, or kinematic.
+ */
+ public setBodyType(type: RigidBodyType, wakeUp: boolean) {
+ return this.rawSet.rbSetBodyType(
+ this.handle,
+ type as number as RawRigidBodyType,
+ wakeUp,
+ );
+ }
+
+ /**
+ * Is this rigid-body sleeping?
+ */
+ public isSleeping(): boolean {
+ return this.rawSet.rbIsSleeping(this.handle);
+ }
+
+ /**
+ * Is the velocity of this rigid-body not zero?
+ */
+ public isMoving(): boolean {
+ return this.rawSet.rbIsMoving(this.handle);
+ }
+
+ /**
+ * Is this rigid-body static?
+ */
+ public isFixed(): boolean {
+ return this.rawSet.rbIsFixed(this.handle);
+ }
+
+ /**
+ * Is this rigid-body kinematic?
+ */
+ public isKinematic(): boolean {
+ return this.rawSet.rbIsKinematic(this.handle);
+ }
+
+ /**
+ * Is this rigid-body dynamic?
+ */
+ public isDynamic(): boolean {
+ return this.rawSet.rbIsDynamic(this.handle);
+ }
+
+ /**
+ * The linear damping coefficient of this rigid-body.
+ */
+ public linearDamping(): number {
+ return this.rawSet.rbLinearDamping(this.handle);
+ }
+
+ /**
+ * The angular damping coefficient of this rigid-body.
+ */
+ public angularDamping(): number {
+ return this.rawSet.rbAngularDamping(this.handle);
+ }
+
+ /**
+ * Sets the linear damping factor applied to this rigid-body.
+ *
+ * @param factor - The damping factor to set.
+ */
+ public setLinearDamping(factor: number) {
+ this.rawSet.rbSetLinearDamping(this.handle, factor);
+ }
+
+ /**
+ * Recompute the mass-properties of this rigid-bodies based on its currently attached colliders.
+ */
+ public recomputeMassPropertiesFromColliders() {
+ this.rawSet.rbRecomputeMassPropertiesFromColliders(
+ this.handle,
+ this.colliderSet.raw,
+ );
+ }
+
+ /**
+ * Sets the rigid-body's additional mass.
+ *
+ * The total angular inertia of the rigid-body will be scaled automatically based on this additional mass. If this
+ * scaling effect isn’t desired, use Self::additional_mass_properties instead of this method.
+ *
+ * This is only the "additional" mass because the total mass of the rigid-body is equal to the sum of this
+ * additional mass and the mass computed from the colliders (with non-zero densities) attached to this rigid-body.
+ *
+ * That total mass (which includes the attached colliders’ contributions) will be updated at the name physics step,
+ * or can be updated manually with `this.recomputeMassPropertiesFromColliders`.
+ *
+ * This will override any previous additional mass-properties set by `this.setAdditionalMass`,
+ * `this.setAdditionalMassProperties`, `RigidBodyDesc::setAdditionalMass`, or
+ * `RigidBodyDesc.setAdditionalMassfProperties` for this rigid-body.
+ *
+ * @param mass - The additional mass to set.
+ * @param wakeUp - If `true` then the rigid-body will be woken up if it was put to sleep because it did not move for a while.
+ */
+ public setAdditionalMass(mass: number, wakeUp: boolean) {
+ this.rawSet.rbSetAdditionalMass(this.handle, mass, wakeUp);
+ }
+
+ // #if DIM3
+ /**
+ * Sets the rigid-body's additional mass-properties.
+ *
+ * This is only the "additional" mass-properties because the total mass-properties of the rigid-body is equal to the
+ * sum of this additional mass-properties and the mass computed from the colliders (with non-zero densities) attached
+ * to this rigid-body.
+ *
+ * That total mass-properties (which include the attached colliders’ contributions) will be updated at the name
+ * physics step, or can be updated manually with `this.recomputeMassPropertiesFromColliders`.
+ *
+ * This will override any previous mass-properties set by `this.setAdditionalMass`,
+ * `this.setAdditionalMassProperties`, `RigidBodyDesc.setAdditionalMass`, or `RigidBodyDesc.setAdditionalMassProperties`
+ * for this rigid-body.
+ *
+ * If `wake_up` is true then the rigid-body will be woken up if it was put to sleep because it did not move for a while.
+ */
+ public setAdditionalMassProperties(
+ mass: number,
+ centerOfMass: Vector,
+ principalAngularInertia: Vector,
+ angularInertiaLocalFrame: Rotation,
+ wakeUp: boolean,
+ ) {
+ let rawCom = VectorOps.intoRaw(centerOfMass);
+ let rawPrincipalInertia = VectorOps.intoRaw(principalAngularInertia);
+ let rawInertiaFrame = RotationOps.intoRaw(angularInertiaLocalFrame);
+
+ this.rawSet.rbSetAdditionalMassProperties(
+ this.handle,
+ mass,
+ rawCom,
+ rawPrincipalInertia,
+ rawInertiaFrame,
+ wakeUp,
+ );
+
+ rawCom.free();
+ rawPrincipalInertia.free();
+ rawInertiaFrame.free();
+ }
+
+ // #endif
+
+ // #if DIM2
+ /**
+ * Sets the rigid-body's additional mass-properties.
+ *
+ * This is only the "additional" mass-properties because the total mass-properties of the rigid-body is equal to the
+ * sum of this additional mass-properties and the mass computed from the colliders (with non-zero densities) attached
+ * to this rigid-body.
+ *
+ * That total mass-properties (which include the attached colliders’ contributions) will be updated at the name
+ * physics step, or can be updated manually with `this.recomputeMassPropertiesFromColliders`.
+ *
+ * This will override any previous mass-properties set by `this.setAdditionalMass`,
+ * `this.setAdditionalMassProperties`, `RigidBodyDesc.setAdditionalMass`, or `RigidBodyDesc.setAdditionalMassProperties`
+ * for this rigid-body.
+ *
+ * If `wake_up` is true then the rigid-body will be woken up if it was put to sleep because it did not move for a while.
+ */
+ public setAdditionalMassProperties(
+ mass: number,
+ centerOfMass: Vector,
+ principalAngularInertia: number,
+ wakeUp: boolean,
+ ) {
+ let rawCom = VectorOps.intoRaw(centerOfMass);
+ this.rawSet.rbSetAdditionalMassProperties(
+ this.handle,
+ mass,
+ rawCom,
+ principalAngularInertia,
+ wakeUp,
+ );
+ rawCom.free();
+ }
+
+ // #endif
+
+ /**
+ * Sets the linear damping factor applied to this rigid-body.
+ *
+ * @param factor - The damping factor to set.
+ */
+ public setAngularDamping(factor: number) {
+ this.rawSet.rbSetAngularDamping(this.handle, factor);
+ }
+
+ /**
+ * Resets to zero the user forces (but not torques) applied to this rigid-body.
+ *
+ * @param wakeUp - should the rigid-body be automatically woken-up?
+ */
+ public resetForces(wakeUp: boolean) {
+ this.rawSet.rbResetForces(this.handle, wakeUp);
+ }
+
+ /**
+ * Resets to zero the user torques applied to this rigid-body.
+ *
+ * @param wakeUp - should the rigid-body be automatically woken-up?
+ */
+ public resetTorques(wakeUp: boolean) {
+ this.rawSet.rbResetTorques(this.handle, wakeUp);
+ }
+
+ /**
+ * Adds a force at the center-of-mass of this rigid-body.
+ *
+ * @param force - the world-space force to add to the rigid-body.
+ * @param wakeUp - should the rigid-body be automatically woken-up?
+ */
+ public addForce(force: Vector, wakeUp: boolean) {
+ const rawForce = VectorOps.intoRaw(force);
+ this.rawSet.rbAddForce(this.handle, rawForce, wakeUp);
+ rawForce.free();
+ }
+
+ /**
+ * Applies an impulse at the center-of-mass of this rigid-body.
+ *
+ * @param impulse - the world-space impulse to apply on the rigid-body.
+ * @param wakeUp - should the rigid-body be automatically woken-up?
+ */
+ public applyImpulse(impulse: Vector, wakeUp: boolean) {
+ const rawImpulse = VectorOps.intoRaw(impulse);
+ this.rawSet.rbApplyImpulse(this.handle, rawImpulse, wakeUp);
+ rawImpulse.free();
+ }
+
+ // #if DIM2
+ /**
+ * Adds a torque at the center-of-mass of this rigid-body.
+ *
+ * @param torque - the torque to add to the rigid-body.
+ * @param wakeUp - should the rigid-body be automatically woken-up?
+ */
+ public addTorque(torque: number, wakeUp: boolean) {
+ this.rawSet.rbAddTorque(this.handle, torque, wakeUp);
+ }
+
+ // #endif
+
+ // #if DIM3
+ /**
+ * Adds a torque at the center-of-mass of this rigid-body.
+ *
+ * @param torque - the world-space torque to add to the rigid-body.
+ * @param wakeUp - should the rigid-body be automatically woken-up?
+ */
+ public addTorque(torque: Vector, wakeUp: boolean) {
+ const rawTorque = VectorOps.intoRaw(torque);
+ this.rawSet.rbAddTorque(this.handle, rawTorque, wakeUp);
+ rawTorque.free();
+ }
+
+ // #endif
+
+ // #if DIM2
+ /**
+ * Applies an impulsive torque at the center-of-mass of this rigid-body.
+ *
+ * @param torqueImpulse - the torque impulse to apply on the rigid-body.
+ * @param wakeUp - should the rigid-body be automatically woken-up?
+ */
+ public applyTorqueImpulse(torqueImpulse: number, wakeUp: boolean) {
+ this.rawSet.rbApplyTorqueImpulse(this.handle, torqueImpulse, wakeUp);
+ }
+
+ // #endif
+
+ // #if DIM3
+ /**
+ * Applies an impulsive torque at the center-of-mass of this rigid-body.
+ *
+ * @param torqueImpulse - the world-space torque impulse to apply on the rigid-body.
+ * @param wakeUp - should the rigid-body be automatically woken-up?
+ */
+ public applyTorqueImpulse(torqueImpulse: Vector, wakeUp: boolean) {
+ const rawTorqueImpulse = VectorOps.intoRaw(torqueImpulse);
+ this.rawSet.rbApplyTorqueImpulse(this.handle, rawTorqueImpulse, wakeUp);
+ rawTorqueImpulse.free();
+ }
+
+ // #endif
+
+ /**
+ * Adds a force at the given world-space point of this rigid-body.
+ *
+ * @param force - the world-space force to add to the rigid-body.
+ * @param point - the world-space point where the impulse is to be applied on the rigid-body.
+ * @param wakeUp - should the rigid-body be automatically woken-up?
+ */
+ public addForceAtPoint(force: Vector, point: Vector, wakeUp: boolean) {
+ const rawForce = VectorOps.intoRaw(force);
+ const rawPoint = VectorOps.intoRaw(point);
+ this.rawSet.rbAddForceAtPoint(this.handle, rawForce, rawPoint, wakeUp);
+ rawForce.free();
+ rawPoint.free();
+ }
+
+ /**
+ * Applies an impulse at the given world-space point of this rigid-body.
+ *
+ * @param impulse - the world-space impulse to apply on the rigid-body.
+ * @param point - the world-space point where the impulse is to be applied on the rigid-body.
+ * @param wakeUp - should the rigid-body be automatically woken-up?
+ */
+ public applyImpulseAtPoint(
+ impulse: Vector,
+ point: Vector,
+ wakeUp: boolean,
+ ) {
+ const rawImpulse = VectorOps.intoRaw(impulse);
+ const rawPoint = VectorOps.intoRaw(point);
+ this.rawSet.rbApplyImpulseAtPoint(
+ this.handle,
+ rawImpulse,
+ rawPoint,
+ wakeUp,
+ );
+ rawImpulse.free();
+ rawPoint.free();
+ }
+
+ /**
+ * Retrieves the constant force(s) the user added to this rigid-body
+ * Returns zero if the rigid-body is not dynamic.
+ *
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public userForce(target?: Vector): Vector {
+ this.rawSet.rbUserForce(this.handle, scratchBuffer);
+ return VectorOps.fromBuffer(scratchBuffer, target);
+ }
+
+ // #if DIM2
+ /**
+ * Retrieves the constant torque(s) the user added to this rigid-body
+ * Returns zero if the rigid-body is not dynamic.
+ */
+ public userTorque(): number {
+ return this.rawSet.rbUserTorque(this.handle);
+ }
+ // #endif
+
+ // #if DIM3
+ /**
+ * Retrieves the constant torque(s) the user added to this rigid-body
+ * Returns zero if the rigid-body is not dynamic.
+ *
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public userTorque(target?: Vector): Vector {
+ this.rawSet.rbUserTorque(this.handle, scratchBuffer);
+ return VectorOps.fromBuffer(scratchBuffer, target);
+ }
+ // #endif
+}
+
+export class RigidBodyDesc {
+ enabled: boolean;
+ translation: Vector;
+ rotation: Rotation;
+ gravityScale: number;
+ mass: number;
+ massOnly: boolean;
+ centerOfMass: Vector;
+ translationsEnabledX: boolean;
+ translationsEnabledY: boolean;
+ linvel: Vector;
+ // #if DIM2
+ angvel: number;
+ principalAngularInertia: number;
+ rotationsEnabled: boolean;
+ // #endif
+ // #if DIM3
+ angvel: Vector;
+ principalAngularInertia: Vector;
+ angularInertiaLocalFrame: Rotation;
+ translationsEnabledZ: boolean;
+ rotationsEnabledX: boolean;
+ rotationsEnabledY: boolean;
+ rotationsEnabledZ: boolean;
+ // #endif
+ linearDamping: number;
+ angularDamping: number;
+ status: RigidBodyType;
+ canSleep: boolean;
+ sleeping: boolean;
+ ccdEnabled: boolean;
+ softCcdPrediction: number;
+ dominanceGroup: number;
+ additionalSolverIterations: number;
+ userData?: unknown;
+
+ constructor(status: RigidBodyType) {
+ this.enabled = true;
+ this.status = status;
+ this.translation = VectorOps.zeros();
+ this.rotation = RotationOps.identity();
+ this.gravityScale = 1.0;
+ this.linvel = VectorOps.zeros();
+ this.mass = 0.0;
+ this.massOnly = false;
+ this.centerOfMass = VectorOps.zeros();
+ this.translationsEnabledX = true;
+ this.translationsEnabledY = true;
+ // #if DIM2
+ this.angvel = 0.0;
+ this.principalAngularInertia = 0.0;
+ this.rotationsEnabled = true;
+ // #endif
+ // #if DIM3
+ this.angvel = VectorOps.zeros();
+ this.principalAngularInertia = VectorOps.zeros();
+ this.angularInertiaLocalFrame = RotationOps.identity();
+ this.translationsEnabledZ = true;
+ this.rotationsEnabledX = true;
+ this.rotationsEnabledY = true;
+ this.rotationsEnabledZ = true;
+ // #endif
+ this.linearDamping = 0.0;
+ this.angularDamping = 0.0;
+ this.canSleep = true;
+ this.sleeping = false;
+ this.ccdEnabled = false;
+ this.softCcdPrediction = 0.0;
+ this.dominanceGroup = 0;
+ this.additionalSolverIterations = 0;
+ }
+
+ /**
+ * A rigid-body descriptor used to build a dynamic rigid-body.
+ */
+ public static dynamic(): RigidBodyDesc {
+ return new RigidBodyDesc(RigidBodyType.Dynamic);
+ }
+
+ /**
+ * A rigid-body descriptor used to build a position-based kinematic rigid-body.
+ */
+ public static kinematicPositionBased(): RigidBodyDesc {
+ return new RigidBodyDesc(RigidBodyType.KinematicPositionBased);
+ }
+
+ /**
+ * A rigid-body descriptor used to build a velocity-based kinematic rigid-body.
+ */
+ public static kinematicVelocityBased(): RigidBodyDesc {
+ return new RigidBodyDesc(RigidBodyType.KinematicVelocityBased);
+ }
+
+ /**
+ * A rigid-body descriptor used to build a fixed rigid-body.
+ */
+ public static fixed(): RigidBodyDesc {
+ return new RigidBodyDesc(RigidBodyType.Fixed);
+ }
+
+ /**
+ * A rigid-body descriptor used to build a dynamic rigid-body.
+ *
+ * @deprecated The method has been renamed to `.dynamic()`.
+ */
+ public static newDynamic(): RigidBodyDesc {
+ return new RigidBodyDesc(RigidBodyType.Dynamic);
+ }
+
+ /**
+ * A rigid-body descriptor used to build a position-based kinematic rigid-body.
+ *
+ * @deprecated The method has been renamed to `.kinematicPositionBased()`.
+ */
+ public static newKinematicPositionBased(): RigidBodyDesc {
+ return new RigidBodyDesc(RigidBodyType.KinematicPositionBased);
+ }
+
+ /**
+ * A rigid-body descriptor used to build a velocity-based kinematic rigid-body.
+ *
+ * @deprecated The method has been renamed to `.kinematicVelocityBased()`.
+ */
+ public static newKinematicVelocityBased(): RigidBodyDesc {
+ return new RigidBodyDesc(RigidBodyType.KinematicVelocityBased);
+ }
+
+ /**
+ * A rigid-body descriptor used to build a fixed rigid-body.
+ *
+ * @deprecated The method has been renamed to `.fixed()`.
+ */
+ public static newStatic(): RigidBodyDesc {
+ return new RigidBodyDesc(RigidBodyType.Fixed);
+ }
+
+ public setDominanceGroup(group: number): RigidBodyDesc {
+ this.dominanceGroup = group;
+ return this;
+ }
+
+ /**
+ * Sets the number of additional solver iterations that will be run for this
+ * rigid-body and everything that interacts with it directly or indirectly
+ * through contacts or joints.
+ *
+ * Compared to increasing the global `World.numSolverIteration`, setting this
+ * value lets you increase accuracy on only a subset of the scene, resulting in reduced
+ * performance loss.
+ *
+ * @param iters - The new number of additional solver iterations (default: 0).
+ */
+ public setAdditionalSolverIterations(iters: number): RigidBodyDesc {
+ this.additionalSolverIterations = iters;
+ return this;
+ }
+
+ /**
+ * Sets whether the created rigid-body will be enabled or disabled.
+ * @param enabled − If set to `false` the rigid-body will be disabled at creation.
+ */
+ public setEnabled(enabled: boolean): RigidBodyDesc {
+ this.enabled = enabled;
+ return this;
+ }
+
+ // #if DIM2
+ /**
+ * Sets the initial translation of the rigid-body to create.
+ */
+ public setTranslation(x: number, y: number): RigidBodyDesc {
+ if (typeof x != "number" || typeof y != "number")
+ throw TypeError("The translation components must be numbers.");
+
+ this.translation = {x: x, y: y};
+ return this;
+ }
+
+ // #endif
+
+ // #if DIM3
+ /**
+ * Sets the initial translation of the rigid-body to create.
+ *
+ * @param tra - The translation to set.
+ */
+ public setTranslation(x: number, y: number, z: number): RigidBodyDesc {
+ if (
+ typeof x != "number" ||
+ typeof y != "number" ||
+ typeof z != "number"
+ )
+ throw TypeError("The translation components must be numbers.");
+
+ this.translation = {x: x, y: y, z: z};
+ return this;
+ }
+
+ // #endif
+
+ /**
+ * Sets the initial rotation of the rigid-body to create.
+ *
+ * @param rot - The rotation to set.
+ */
+ public setRotation(rot: Rotation): RigidBodyDesc {
+ // #if DIM2
+ this.rotation = rot;
+ // #endif
+ // #if DIM3
+ RotationOps.copy(this.rotation, rot);
+ // #endif
+ return this;
+ }
+
+ /**
+ * Sets the scale factor applied to the gravity affecting
+ * the rigid-body being built.
+ *
+ * @param scale - The scale factor. Set this to `0.0` if the rigid-body
+ * needs to ignore gravity.
+ */
+ public setGravityScale(scale: number): RigidBodyDesc {
+ this.gravityScale = scale;
+ return this;
+ }
+
+ /**
+ * Sets the initial mass of the rigid-body being built, before adding colliders' contributions.
+ *
+ * @param mass − The initial mass of the rigid-body to create.
+ */
+ public setAdditionalMass(mass: number): RigidBodyDesc {
+ this.mass = mass;
+ this.massOnly = true;
+ return this;
+ }
+
+ // #if DIM2
+ /**
+ * Sets the initial linear velocity of the rigid-body to create.
+ *
+ * @param x - The linear velocity to set along the `x` axis.
+ * @param y - The linear velocity to set along the `y` axis.
+ */
+ public setLinvel(x: number, y: number): RigidBodyDesc {
+ if (typeof x != "number" || typeof y != "number")
+ throw TypeError("The linvel components must be numbers.");
+
+ this.linvel = {x: x, y: y};
+ return this;
+ }
+
+ /**
+ * Sets the initial angular velocity of the rigid-body to create.
+ *
+ * @param vel - The angular velocity to set.
+ */
+ public setAngvel(vel: number): RigidBodyDesc {
+ this.angvel = vel;
+ return this;
+ }
+
+ /**
+ * Sets the mass properties of the rigid-body being built.
+ *
+ * Note that the final mass properties of the rigid-bodies depends
+ * on the initial mass-properties of the rigid-body (set by this method)
+ * to which is added the contributions of all the colliders with non-zero density
+ * attached to this rigid-body.
+ *
+ * Therefore, if you want your provided mass properties to be the final
+ * mass properties of your rigid-body, don't attach colliders to it, or
+ * only attach colliders with densities equal to zero.
+ *
+ * @param mass − The initial mass of the rigid-body to create.
+ * @param centerOfMass − The initial center-of-mass of the rigid-body to create.
+ * @param principalAngularInertia − The initial principal angular inertia of the rigid-body to create.
+ */
+ public setAdditionalMassProperties(
+ mass: number,
+ centerOfMass: Vector,
+ principalAngularInertia: number,
+ ): RigidBodyDesc {
+ this.mass = mass;
+ VectorOps.copy(this.centerOfMass, centerOfMass);
+ this.principalAngularInertia = principalAngularInertia;
+ this.massOnly = false;
+ return this;
+ }
+
+ /**
+ * Allow translation of this rigid-body only along specific axes.
+ * @param translationsEnabledX - Are translations along the X axis enabled?
+ * @param translationsEnabledY - Are translations along the y axis enabled?
+ */
+ public enabledTranslations(
+ translationsEnabledX: boolean,
+ translationsEnabledY: boolean,
+ ): RigidBodyDesc {
+ this.translationsEnabledX = translationsEnabledX;
+ this.translationsEnabledY = translationsEnabledY;
+ return this;
+ }
+
+ /**
+ * Allow translation of this rigid-body only along specific axes.
+ * @param translationsEnabledX - Are translations along the X axis enabled?
+ * @param translationsEnabledY - Are translations along the y axis enabled?
+ * @deprecated use `this.enabledTranslations` with the same arguments instead.
+ */
+ public restrictTranslations(
+ translationsEnabledX: boolean,
+ translationsEnabledY: boolean,
+ ): RigidBodyDesc {
+ return this.enabledTranslations(
+ translationsEnabledX,
+ translationsEnabledY,
+ );
+ }
+
+ /**
+ * Locks all translations that would have resulted from forces on
+ * the created rigid-body.
+ */
+ public lockTranslations(): RigidBodyDesc {
+ return this.restrictTranslations(false, false);
+ }
+
+ /**
+ * Locks all rotations that would have resulted from forces on
+ * the created rigid-body.
+ */
+ public lockRotations(): RigidBodyDesc {
+ this.rotationsEnabled = false;
+ return this;
+ }
+
+ // #endif
+
+ // #if DIM3
+ /**
+ * Sets the initial linear velocity of the rigid-body to create.
+ *
+ * @param x - The linear velocity to set along the `x` axis.
+ * @param y - The linear velocity to set along the `y` axis.
+ * @param z - The linear velocity to set along the `z` axis.
+ */
+ public setLinvel(x: number, y: number, z: number): RigidBodyDesc {
+ if (
+ typeof x != "number" ||
+ typeof y != "number" ||
+ typeof z != "number"
+ )
+ throw TypeError("The linvel components must be numbers.");
+
+ this.linvel = {x: x, y: y, z: z};
+ return this;
+ }
+
+ /**
+ * Sets the initial angular velocity of the rigid-body to create.
+ *
+ * @param vel - The angular velocity to set.
+ */
+ public setAngvel(vel: Vector): RigidBodyDesc {
+ VectorOps.copy(this.angvel, vel);
+ return this;
+ }
+
+ /**
+ * Sets the mass properties of the rigid-body being built.
+ *
+ * Note that the final mass properties of the rigid-bodies depends
+ * on the initial mass-properties of the rigid-body (set by this method)
+ * to which is added the contributions of all the colliders with non-zero density
+ * attached to this rigid-body.
+ *
+ * Therefore, if you want your provided mass properties to be the final
+ * mass properties of your rigid-body, don't attach colliders to it, or
+ * only attach colliders with densities equal to zero.
+ *
+ * @param mass − The initial mass of the rigid-body to create.
+ * @param centerOfMass − The initial center-of-mass of the rigid-body to create.
+ * @param principalAngularInertia − The initial principal angular inertia of the rigid-body to create.
+ * These are the eigenvalues of the angular inertia matrix.
+ * @param angularInertiaLocalFrame − The initial local angular inertia frame of the rigid-body to create.
+ * These are the eigenvectors of the angular inertia matrix.
+ */
+ public setAdditionalMassProperties(
+ mass: number,
+ centerOfMass: Vector,
+ principalAngularInertia: Vector,
+ angularInertiaLocalFrame: Rotation,
+ ): RigidBodyDesc {
+ this.mass = mass;
+ VectorOps.copy(this.centerOfMass, centerOfMass);
+ VectorOps.copy(this.principalAngularInertia, principalAngularInertia);
+ RotationOps.copy(
+ this.angularInertiaLocalFrame,
+ angularInertiaLocalFrame,
+ );
+ this.massOnly = false;
+ return this;
+ }
+
+ /**
+ * Allow translation of this rigid-body only along specific axes.
+ * @param translationsEnabledX - Are translations along the X axis enabled?
+ * @param translationsEnabledY - Are translations along the y axis enabled?
+ * @param translationsEnabledZ - Are translations along the Z axis enabled?
+ */
+ public enabledTranslations(
+ translationsEnabledX: boolean,
+ translationsEnabledY: boolean,
+ translationsEnabledZ: boolean,
+ ): RigidBodyDesc {
+ this.translationsEnabledX = translationsEnabledX;
+ this.translationsEnabledY = translationsEnabledY;
+ this.translationsEnabledZ = translationsEnabledZ;
+ return this;
+ }
+
+ /**
+ * Allow translation of this rigid-body only along specific axes.
+ * @param translationsEnabledX - Are translations along the X axis enabled?
+ * @param translationsEnabledY - Are translations along the y axis enabled?
+ * @param translationsEnabledZ - Are translations along the Z axis enabled?
+ * @deprecated use `this.enabledTranslations` with the same arguments instead.
+ */
+ public restrictTranslations(
+ translationsEnabledX: boolean,
+ translationsEnabledY: boolean,
+ translationsEnabledZ: boolean,
+ ): RigidBodyDesc {
+ return this.enabledTranslations(
+ translationsEnabledX,
+ translationsEnabledY,
+ translationsEnabledZ,
+ );
+ }
+
+ /**
+ * Locks all translations that would have resulted from forces on
+ * the created rigid-body.
+ */
+ public lockTranslations(): RigidBodyDesc {
+ return this.enabledTranslations(false, false, false);
+ }
+
+ /**
+ * Allow rotation of this rigid-body only along specific axes.
+ * @param rotationsEnabledX - Are rotations along the X axis enabled?
+ * @param rotationsEnabledY - Are rotations along the y axis enabled?
+ * @param rotationsEnabledZ - Are rotations along the Z axis enabled?
+ */
+ public enabledRotations(
+ rotationsEnabledX: boolean,
+ rotationsEnabledY: boolean,
+ rotationsEnabledZ: boolean,
+ ): RigidBodyDesc {
+ this.rotationsEnabledX = rotationsEnabledX;
+ this.rotationsEnabledY = rotationsEnabledY;
+ this.rotationsEnabledZ = rotationsEnabledZ;
+ return this;
+ }
+
+ /**
+ * Allow rotation of this rigid-body only along specific axes.
+ * @param rotationsEnabledX - Are rotations along the X axis enabled?
+ * @param rotationsEnabledY - Are rotations along the y axis enabled?
+ * @param rotationsEnabledZ - Are rotations along the Z axis enabled?
+ * @deprecated use `this.enabledRotations` with the same arguments instead.
+ */
+ public restrictRotations(
+ rotationsEnabledX: boolean,
+ rotationsEnabledY: boolean,
+ rotationsEnabledZ: boolean,
+ ): RigidBodyDesc {
+ return this.enabledRotations(
+ rotationsEnabledX,
+ rotationsEnabledY,
+ rotationsEnabledZ,
+ );
+ }
+
+ /**
+ * Locks all rotations that would have resulted from forces on
+ * the created rigid-body.
+ */
+ public lockRotations(): RigidBodyDesc {
+ return this.restrictRotations(false, false, false);
+ }
+
+ // #endif
+
+ /**
+ * Sets the linear damping of the rigid-body to create.
+ *
+ * This will progressively slowdown the translational movement of the rigid-body.
+ *
+ * @param damping - The angular damping coefficient. Should be >= 0. The higher this
+ * value is, the stronger the translational slowdown will be.
+ */
+ public setLinearDamping(damping: number): RigidBodyDesc {
+ this.linearDamping = damping;
+ return this;
+ }
+
+ /**
+ * Sets the angular damping of the rigid-body to create.
+ *
+ * This will progressively slowdown the rotational movement of the rigid-body.
+ *
+ * @param damping - The angular damping coefficient. Should be >= 0. The higher this
+ * value is, the stronger the rotational slowdown will be.
+ */
+ public setAngularDamping(damping: number): RigidBodyDesc {
+ this.angularDamping = damping;
+ return this;
+ }
+
+ /**
+ * Sets whether or not the rigid-body to create can sleep.
+ *
+ * @param can - true if the rigid-body can sleep, false if it can't.
+ */
+ public setCanSleep(can: boolean): RigidBodyDesc {
+ this.canSleep = can;
+ return this;
+ }
+
+ /**
+ * Sets whether or not the rigid-body is to be created asleep.
+ *
+ * @param can - true if the rigid-body should be in sleep, default false.
+ */
+ setSleeping(sleeping: boolean): RigidBodyDesc {
+ this.sleeping = sleeping;
+ return this;
+ }
+
+ /**
+ * Sets whether Continuous Collision Detection (CCD) is enabled for this rigid-body.
+ *
+ * @param enabled - true if the rigid-body has CCD enabled.
+ */
+ public setCcdEnabled(enabled: boolean): RigidBodyDesc {
+ this.ccdEnabled = enabled;
+ return this;
+ }
+
+ /**
+ * Sets the maximum prediction distance Soft Continuous Collision-Detection.
+ *
+ * When set to 0, soft-CCD is disabled. Soft-CCD helps prevent tunneling especially of
+ * slow-but-thin to moderately fast objects. The soft CCD prediction distance indicates how
+ * far in the object’s path the CCD algorithm is allowed to inspect. Large values can impact
+ * performance badly by increasing the work needed from the broad-phase.
+ *
+ * It is a generally cheaper variant of regular CCD (that can be enabled with
+ * `RigidBodyDesc::setCcdEnabled` since it relies on predictive constraints instead of
+ * shape-cast and substeps.
+ */
+ public setSoftCcdPrediction(distance: number): RigidBodyDesc {
+ this.softCcdPrediction = distance;
+ return this;
+ }
+
+ /**
+ * Sets the user-defined object of this rigid-body.
+ *
+ * @param userData - The user-defined object to set.
+ */
+ public setUserData(data?: unknown): RigidBodyDesc {
+ this.userData = data;
+ return this;
+ }
+}
diff --git a/typescript/src.ts/dynamics/rigid_body_set.ts b/typescript/src.ts/dynamics/rigid_body_set.ts
new file mode 100644
index 000000000..4c2e47bd5
--- /dev/null
+++ b/typescript/src.ts/dynamics/rigid_body_set.ts
@@ -0,0 +1,238 @@
+import {RawRigidBodySet, RawRigidBodyType} from "../raw";
+import {Coarena} from "../coarena";
+import {VectorOps, RotationOps} from "../math";
+import {
+ RigidBody,
+ RigidBodyDesc,
+ RigidBodyHandle,
+ RigidBodyType,
+} from "./rigid_body";
+import {ColliderSet} from "../geometry";
+import {ImpulseJointSet} from "./impulse_joint_set";
+import {MultibodyJointSet} from "./multibody_joint_set";
+import {IslandManager} from "./island_manager";
+
+/**
+ * A set of rigid bodies that can be handled by a physics pipeline.
+ *
+ * To avoid leaking WASM resources, this MUST be freed manually with `rigidBodySet.free()`
+ * once you are done using it (and all the rigid-bodies it created).
+ */
+export class RigidBodySet {
+ raw: RawRigidBodySet;
+ private map: Coarena;
+
+ /**
+ * Release the WASM memory occupied by this rigid-body set.
+ */
+ public free() {
+ if (!!this.raw) {
+ this.raw.free();
+ }
+ this.raw = undefined;
+
+ if (!!this.map) {
+ this.map.clear();
+ }
+ this.map = undefined;
+ }
+
+ constructor(raw?: RawRigidBodySet) {
+ this.raw = raw || new RawRigidBodySet();
+ this.map = new Coarena();
+ // deserialize
+ if (raw) {
+ raw.forEachRigidBodyHandle((handle: RigidBodyHandle) => {
+ this.map.set(handle, new RigidBody(raw, null, handle));
+ });
+ }
+ }
+
+ /**
+ * Internal method, do not call this explicitly.
+ */
+ public finalizeDeserialization(colliderSet: ColliderSet) {
+ this.map.forEach((rb) => rb.finalizeDeserialization(colliderSet));
+ }
+
+ /**
+ * Creates a new rigid-body and return its integer handle.
+ *
+ * @param desc - The description of the rigid-body to create.
+ */
+ public createRigidBody(
+ colliderSet: ColliderSet,
+ desc: RigidBodyDesc,
+ ): RigidBody {
+ let rawTra = VectorOps.intoRaw(desc.translation);
+ let rawRot = RotationOps.intoRaw(desc.rotation);
+ let rawLv = VectorOps.intoRaw(desc.linvel);
+ let rawCom = VectorOps.intoRaw(desc.centerOfMass);
+
+ // #if DIM3
+ let rawAv = VectorOps.intoRaw(desc.angvel);
+ let rawPrincipalInertia = VectorOps.intoRaw(
+ desc.principalAngularInertia,
+ );
+ let rawInertiaFrame = RotationOps.intoRaw(
+ desc.angularInertiaLocalFrame,
+ );
+ // #endif
+
+ let handle = this.raw.createRigidBody(
+ desc.enabled,
+ rawTra,
+ rawRot,
+ desc.gravityScale,
+ desc.mass,
+ desc.massOnly,
+ rawCom,
+ rawLv,
+ // #if DIM2
+ desc.angvel,
+ desc.principalAngularInertia,
+ desc.translationsEnabledX,
+ desc.translationsEnabledY,
+ desc.rotationsEnabled,
+ // #endif
+ // #if DIM3
+ rawAv,
+ rawPrincipalInertia,
+ rawInertiaFrame,
+ desc.translationsEnabledX,
+ desc.translationsEnabledY,
+ desc.translationsEnabledZ,
+ desc.rotationsEnabledX,
+ desc.rotationsEnabledY,
+ desc.rotationsEnabledZ,
+ // #endif
+ desc.linearDamping,
+ desc.angularDamping,
+ desc.status as number as RawRigidBodyType,
+ desc.canSleep,
+ desc.sleeping,
+ desc.softCcdPrediction,
+ desc.ccdEnabled,
+ desc.dominanceGroup,
+ desc.additionalSolverIterations,
+ );
+
+ rawTra.free();
+ rawRot.free();
+ rawLv.free();
+ rawCom.free();
+
+ // #if DIM3
+ rawAv.free();
+ rawPrincipalInertia.free();
+ rawInertiaFrame.free();
+ // #endif
+
+ const body = new RigidBody(this.raw, colliderSet, handle);
+ body.userData = desc.userData;
+
+ this.map.set(handle, body);
+
+ return body;
+ }
+
+ /**
+ * Removes a rigid-body from this set.
+ *
+ * This will also remove all the colliders and joints attached to the rigid-body.
+ *
+ * @param handle - The integer handle of the rigid-body to remove.
+ * @param colliders - The set of colliders that may contain colliders attached to the removed rigid-body.
+ * @param impulseJoints - The set of impulse joints that may contain joints attached to the removed rigid-body.
+ * @param multibodyJoints - The set of multibody joints that may contain joints attached to the removed rigid-body.
+ */
+ public remove(
+ handle: RigidBodyHandle,
+ islands: IslandManager,
+ colliders: ColliderSet,
+ impulseJoints: ImpulseJointSet,
+ multibodyJoints: MultibodyJointSet,
+ ) {
+ // Unmap the entities that will be removed automatically because of the rigid-body removals.
+ for (let i = 0; i < this.raw.rbNumColliders(handle); i += 1) {
+ colliders.unmap(this.raw.rbCollider(handle, i));
+ }
+
+ impulseJoints.forEachJointHandleAttachedToRigidBody(handle, (handle) =>
+ impulseJoints.unmap(handle),
+ );
+ multibodyJoints.forEachJointHandleAttachedToRigidBody(
+ handle,
+ (handle) => multibodyJoints.unmap(handle),
+ );
+
+ // Remove the rigid-body.
+ this.raw.remove(
+ handle,
+ islands.raw,
+ colliders.raw,
+ impulseJoints.raw,
+ multibodyJoints.raw,
+ );
+ this.map.delete(handle);
+ }
+
+ /**
+ * The number of rigid-bodies on this set.
+ */
+ public len(): number {
+ return this.map.len();
+ }
+
+ /**
+ * Does this set contain a rigid-body with the given handle?
+ *
+ * @param handle - The rigid-body handle to check.
+ */
+ public contains(handle: RigidBodyHandle): boolean {
+ return this.get(handle) != null;
+ }
+
+ /**
+ * Gets the rigid-body with the given handle.
+ *
+ * @param handle - The handle of the rigid-body to retrieve.
+ */
+ public get(handle: RigidBodyHandle): RigidBody | null {
+ return this.map.get(handle);
+ }
+
+ /**
+ * Applies the given closure to each rigid-body contained by this set.
+ *
+ * @param f - The closure to apply.
+ */
+ public forEach(f: (body: RigidBody) => void) {
+ this.map.forEach(f);
+ }
+
+ /**
+ * Applies the given closure to each active rigid-bodies contained by this set.
+ *
+ * A rigid-body is active if it is not sleeping, i.e., if it moved recently.
+ *
+ * @param f - The closure to apply.
+ */
+ public forEachActiveRigidBody(
+ islands: IslandManager,
+ f: (body: RigidBody) => void,
+ ) {
+ islands.forEachActiveRigidBodyHandle((handle) => {
+ f(this.get(handle));
+ });
+ }
+
+ /**
+ * Gets all rigid-bodies in the list.
+ *
+ * @returns rigid-bodies list.
+ */
+ public getAll(): RigidBody[] {
+ return this.map.getAll();
+ }
+}
diff --git a/typescript/src.ts/exports.ts b/typescript/src.ts/exports.ts
new file mode 100644
index 000000000..237bd5451
--- /dev/null
+++ b/typescript/src.ts/exports.ts
@@ -0,0 +1,27 @@
+import {version as vers, reserve_memory as reserve} from "./raw";
+
+export function version(): string {
+ return vers();
+}
+
+/// Reserves additional memory in WASM land.
+///
+/// This will grow the internal WASM memory buffer so that it can fit at least
+/// the specified amount of extra bytes. This can help reduce future runtime
+/// overhead due to dynamic internal memory growth once the limit of the
+/// pre-allocated memory is reached.
+///
+/// This feature is still experimental. Due to the nature of the internal
+/// allocator, there can be situations where the allocator decides to perform
+/// additional internal memory growth even though not all `extraBytesCount`
+/// are occupied yet.
+export function reserveMemory(extraBytesCount: number) {
+ reserve(extraBytesCount);
+}
+
+export * from "./math";
+export * from "./dynamics";
+export * from "./geometry";
+export * from "./pipeline";
+export * from "./init";
+export * from "./control";
diff --git a/typescript/src.ts/geometry/broad_phase.ts b/typescript/src.ts/geometry/broad_phase.ts
new file mode 100644
index 000000000..7101ec3f7
--- /dev/null
+++ b/typescript/src.ts/geometry/broad_phase.ts
@@ -0,0 +1,539 @@
+import {RawBroadPhase, RawRayColliderIntersection} from "../raw";
+import {RigidBodyHandle, RigidBodySet} from "../dynamics";
+import {ColliderSet} from "./collider_set";
+import {Ray, RayColliderHit, RayColliderIntersection} from "./ray";
+import {InteractionGroups} from "./interaction_groups";
+import {ColliderHandle} from "./collider";
+import {Rotation, RotationOps, Vector, VectorOps, scratchBuffer} from "../math";
+import {Shape} from "./shape";
+import {PointColliderProjection} from "./point";
+import {ColliderShapeCastHit} from "./toi";
+import {QueryFilterFlags} from "../pipeline";
+import {NarrowPhase} from "./narrow_phase";
+
+/**
+ * The broad-phase used for coarse collision-detection.
+ *
+ * To avoid leaking WASM resources, this MUST be freed manually with `broadPhase.free()`
+ * once you are done using it.
+ */
+export class BroadPhase {
+ raw: RawBroadPhase;
+
+ /**
+ * Release the WASM memory occupied by this broad-phase.
+ */
+ public free() {
+ if (!!this.raw) {
+ this.raw.free();
+ }
+ this.raw = undefined;
+ }
+
+ constructor(raw?: RawBroadPhase) {
+ this.raw = raw || new RawBroadPhase();
+ }
+
+ /**
+ * Find the closest intersection between a ray and a set of collider.
+ *
+ * @param colliders - The set of colliders taking part in this pipeline.
+ * @param ray - The ray to cast.
+ * @param maxToi - The maximum time-of-impact that can be reported by this cast. This effectively
+ * limits the length of the ray to `ray.dir.norm() * maxToi`.
+ * @param solid - If `false` then the ray will attempt to hit the boundary of a shape, even if its
+ * origin already lies inside of a shape. In other terms, `true` implies that all shapes are plain,
+ * whereas `false` implies that all shapes are hollow for this ray-cast.
+ * @param groups - Used to filter the colliders that can or cannot be hit by the ray.
+ * @param filter - The callback to filter out which collider will be hit.
+ */
+ public castRay(
+ narrowPhase: NarrowPhase,
+ bodies: RigidBodySet,
+ colliders: ColliderSet,
+ ray: Ray,
+ maxToi: number,
+ solid: boolean,
+ filterFlags?: QueryFilterFlags,
+ filterGroups?: InteractionGroups,
+ filterExcludeCollider?: ColliderHandle,
+ filterExcludeRigidBody?: RigidBodyHandle,
+ filterPredicate?: (collider: ColliderHandle) => boolean,
+ ): RayColliderHit | null {
+ let rawOrig = VectorOps.intoRaw(ray.origin);
+ let rawDir = VectorOps.intoRaw(ray.dir);
+ let result = RayColliderHit.fromRaw(
+ colliders,
+ this.raw.castRay(
+ narrowPhase.raw,
+ bodies.raw,
+ colliders.raw,
+ rawOrig,
+ rawDir,
+ maxToi,
+ solid,
+ filterFlags,
+ filterGroups,
+ filterExcludeCollider,
+ filterExcludeRigidBody,
+ filterPredicate,
+ ),
+ );
+
+ rawOrig.free();
+ rawDir.free();
+
+ return result;
+ }
+
+ /**
+ * Find the closest intersection between a ray and a set of collider.
+ *
+ * This also computes the normal at the hit point.
+ * @param colliders - The set of colliders taking part in this pipeline.
+ * @param ray - The ray to cast.
+ * @param maxToi - The maximum time-of-impact that can be reported by this cast. This effectively
+ * limits the length of the ray to `ray.dir.norm() * maxToi`.
+ * @param solid - If `false` then the ray will attempt to hit the boundary of a shape, even if its
+ * origin already lies inside of a shape. In other terms, `true` implies that all shapes are plain,
+ * whereas `false` implies that all shapes are hollow for this ray-cast.
+ * @param groups - Used to filter the colliders that can or cannot be hit by the ray.
+ */
+ public castRayAndGetNormal(
+ narrowPhase: NarrowPhase,
+ bodies: RigidBodySet,
+ colliders: ColliderSet,
+ ray: Ray,
+ maxToi: number,
+ solid: boolean,
+ filterFlags?: QueryFilterFlags,
+ filterGroups?: InteractionGroups,
+ filterExcludeCollider?: ColliderHandle,
+ filterExcludeRigidBody?: RigidBodyHandle,
+ filterPredicate?: (collider: ColliderHandle) => boolean,
+ target?: RayColliderIntersection,
+ ): RayColliderIntersection | null {
+ let rawOrig = VectorOps.intoRaw(ray.origin);
+ let rawDir = VectorOps.intoRaw(ray.dir);
+ let result = RayColliderIntersection.fromBuffer(
+ colliders,
+ this.raw.castRayAndGetNormal(
+ narrowPhase.raw,
+ bodies.raw,
+ colliders.raw,
+ rawOrig,
+ rawDir,
+ maxToi,
+ solid,
+ filterFlags,
+ filterGroups,
+ filterExcludeCollider,
+ filterExcludeRigidBody,
+ filterPredicate,
+ ),
+ target,
+ );
+
+ rawOrig.free();
+ rawDir.free();
+
+ return result;
+ }
+
+ /**
+ * Cast a ray and collects all the intersections between a ray and the scene.
+ *
+ * @param colliders - The set of colliders taking part in this pipeline.
+ * @param ray - The ray to cast.
+ * @param maxToi - The maximum time-of-impact that can be reported by this cast. This effectively
+ * limits the length of the ray to `ray.dir.norm() * maxToi`.
+ * @param solid - If `false` then the ray will attempt to hit the boundary of a shape, even if its
+ * origin already lies inside of a shape. In other terms, `true` implies that all shapes are plain,
+ * whereas `false` implies that all shapes are hollow for this ray-cast.
+ * @param groups - Used to filter the colliders that can or cannot be hit by the ray.
+ * @param callback - The callback called once per hit (in no particular order) between a ray and a collider.
+ * If this callback returns `false`, then the cast will stop and no further hits will be detected/reported.
+ */
+ public intersectionsWithRay(
+ narrowPhase: NarrowPhase,
+ bodies: RigidBodySet,
+ colliders: ColliderSet,
+ ray: Ray,
+ maxToi: number,
+ solid: boolean,
+ callback: (intersect: RayColliderIntersection) => boolean,
+ filterFlags?: QueryFilterFlags,
+ filterGroups?: InteractionGroups,
+ filterExcludeCollider?: ColliderHandle,
+ filterExcludeRigidBody?: RigidBodyHandle,
+ filterPredicate?: (collider: ColliderHandle) => boolean,
+ ) {
+ let rawOrig = VectorOps.intoRaw(ray.origin);
+ let rawDir = VectorOps.intoRaw(ray.dir);
+ let rawCallback = (rawInter: RawRayColliderIntersection) => {
+ return callback(
+ RayColliderIntersection.fromBuffer(colliders, rawInter),
+ );
+ };
+
+ this.raw.intersectionsWithRay(
+ narrowPhase.raw,
+ bodies.raw,
+ colliders.raw,
+ rawOrig,
+ rawDir,
+ maxToi,
+ solid,
+ rawCallback,
+ filterFlags,
+ filterGroups,
+ filterExcludeCollider,
+ filterExcludeRigidBody,
+ filterPredicate,
+ );
+
+ rawOrig.free();
+ rawDir.free();
+ }
+
+ /**
+ * Gets the handle of up to one collider intersecting the given shape.
+ *
+ * @param colliders - The set of colliders taking part in this pipeline.
+ * @param shapePos - The position of the shape used for the intersection test.
+ * @param shapeRot - The orientation of the shape used for the intersection test.
+ * @param shape - The shape used for the intersection test.
+ * @param groups - The bit groups and filter associated to the ray, in order to only
+ * hit the colliders with collision groups compatible with the ray's group.
+ */
+ public intersectionWithShape(
+ narrowPhase: NarrowPhase,
+ bodies: RigidBodySet,
+ colliders: ColliderSet,
+ shapePos: Vector,
+ shapeRot: Rotation,
+ shape: Shape,
+ filterFlags?: QueryFilterFlags,
+ filterGroups?: InteractionGroups,
+ filterExcludeCollider?: ColliderHandle,
+ filterExcludeRigidBody?: RigidBodyHandle,
+ filterPredicate?: (collider: ColliderHandle) => boolean,
+ ): ColliderHandle | null {
+ let rawPos = VectorOps.intoRaw(shapePos);
+ let rawRot = RotationOps.intoRaw(shapeRot);
+ let rawShape = shape.intoRaw();
+ let result = this.raw.intersectionWithShape(
+ narrowPhase.raw,
+ bodies.raw,
+ colliders.raw,
+ rawPos,
+ rawRot,
+ rawShape,
+ filterFlags,
+ filterGroups,
+ filterExcludeCollider,
+ filterExcludeRigidBody,
+ filterPredicate,
+ );
+
+ rawPos.free();
+ rawRot.free();
+ rawShape.free();
+
+ return result;
+ }
+
+ /**
+ * Find the projection of a point on the closest collider.
+ *
+ * @param colliders - The set of colliders taking part in this pipeline.
+ * @param point - The point to project.
+ * @param solid - If this is set to `true` then the collider shapes are considered to
+ * be plain (if the point is located inside of a plain shape, its projection is the point
+ * itself). If it is set to `false` the collider shapes are considered to be hollow
+ * (if the point is located inside of an hollow shape, it is projected on the shape's
+ * boundary).
+ * @param groups - The bit groups and filter associated to the point to project, in order to only
+ * project on colliders with collision groups compatible with the ray's group.
+ */
+ public projectPoint(
+ narrowPhase: NarrowPhase,
+ bodies: RigidBodySet,
+ colliders: ColliderSet,
+ point: Vector,
+ solid: boolean,
+ filterFlags?: QueryFilterFlags,
+ filterGroups?: InteractionGroups,
+ filterExcludeCollider?: ColliderHandle,
+ filterExcludeRigidBody?: RigidBodyHandle,
+ filterPredicate?: (collider: ColliderHandle) => boolean,
+ target?: PointColliderProjection,
+ ): PointColliderProjection | null {
+ let rawPoint = VectorOps.intoRaw(point);
+ let result = PointColliderProjection.fromBuffer(
+ colliders,
+ this.raw.projectPoint(
+ narrowPhase.raw,
+ bodies.raw,
+ colliders.raw,
+ rawPoint,
+ solid,
+ filterFlags,
+ filterGroups,
+ filterExcludeCollider,
+ filterExcludeRigidBody,
+ filterPredicate,
+ ),
+ target,
+ );
+
+ rawPoint.free();
+
+ return result;
+ }
+
+ /**
+ * Find the projection of a point on the closest collider.
+ *
+ * @param colliders - The set of colliders taking part in this pipeline.
+ * @param point - The point to project.
+ * @param groups - The bit groups and filter associated to the point to project, in order to only
+ * project on colliders with collision groups compatible with the ray's group.
+ */
+ public projectPointAndGetFeature(
+ narrowPhase: NarrowPhase,
+ bodies: RigidBodySet,
+ colliders: ColliderSet,
+ point: Vector,
+ filterFlags?: QueryFilterFlags,
+ filterGroups?: InteractionGroups,
+ filterExcludeCollider?: ColliderHandle,
+ filterExcludeRigidBody?: RigidBodyHandle,
+ filterPredicate?: (collider: ColliderHandle) => boolean,
+ target?: PointColliderProjection,
+ ): PointColliderProjection | null {
+ let rawPoint = VectorOps.intoRaw(point);
+ let result = PointColliderProjection.fromBuffer(
+ colliders,
+ this.raw.projectPointAndGetFeature(
+ narrowPhase.raw,
+ bodies.raw,
+ colliders.raw,
+ rawPoint,
+ filterFlags,
+ filterGroups,
+ filterExcludeCollider,
+ filterExcludeRigidBody,
+ filterPredicate,
+ ),
+ target,
+ );
+
+ rawPoint.free();
+
+ return result;
+ }
+
+ /**
+ * Find all the colliders containing the given point.
+ *
+ * @param colliders - The set of colliders taking part in this pipeline.
+ * @param point - The point used for the containment test.
+ * @param groups - The bit groups and filter associated to the point to test, in order to only
+ * test on colliders with collision groups compatible with the ray's group.
+ * @param callback - A function called with the handles of each collider with a shape
+ * containing the `point`.
+ */
+ public intersectionsWithPoint(
+ narrowPhase: NarrowPhase,
+ bodies: RigidBodySet,
+ colliders: ColliderSet,
+ point: Vector,
+ callback: (handle: ColliderHandle) => boolean,
+ filterFlags?: QueryFilterFlags,
+ filterGroups?: InteractionGroups,
+ filterExcludeCollider?: ColliderHandle,
+ filterExcludeRigidBody?: RigidBodyHandle,
+ filterPredicate?: (collider: ColliderHandle) => boolean,
+ ) {
+ let rawPoint = VectorOps.intoRaw(point);
+
+ this.raw.intersectionsWithPoint(
+ narrowPhase.raw,
+ bodies.raw,
+ colliders.raw,
+ rawPoint,
+ callback,
+ filterFlags,
+ filterGroups,
+ filterExcludeCollider,
+ filterExcludeRigidBody,
+ filterPredicate,
+ );
+
+ rawPoint.free();
+ }
+
+ /**
+ * Casts a shape at a constant linear velocity and retrieve the first collider it hits.
+ * This is similar to ray-casting except that we are casting a whole shape instead of
+ * just a point (the ray origin).
+ *
+ * @param colliders - The set of colliders taking part in this pipeline.
+ * @param shapePos - The initial position of the shape to cast.
+ * @param shapeRot - The initial rotation of the shape to cast.
+ * @param shapeVel - The constant velocity of the shape to cast (i.e. the cast direction).
+ * @param shape - The shape to cast.
+ * @param targetDistance − If the shape moves closer to this distance from a collider, a hit
+ * will be returned.
+ * @param maxToi - The maximum time-of-impact that can be reported by this cast. This effectively
+ * limits the distance traveled by the shape to `shapeVel.norm() * maxToi`.
+ * @param stopAtPenetration - If set to `false`, the linear shape-cast won’t immediately stop if
+ * the shape is penetrating another shape at its starting point **and** its trajectory is such
+ * that it’s on a path to exit that penetration state.
+ * @param groups - The bit groups and filter associated to the shape to cast, in order to only
+ * test on colliders with collision groups compatible with this group.
+ * @param {ColliderShapeCastHit?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public castShape(
+ narrowPhase: NarrowPhase,
+ bodies: RigidBodySet,
+ colliders: ColliderSet,
+ shapePos: Vector,
+ shapeRot: Rotation,
+ shapeVel: Vector,
+ shape: Shape,
+ targetDistance: number,
+ maxToi: number,
+ stopAtPenetration: boolean,
+ filterFlags?: QueryFilterFlags,
+ filterGroups?: InteractionGroups,
+ filterExcludeCollider?: ColliderHandle,
+ filterExcludeRigidBody?: RigidBodyHandle,
+ filterPredicate?: (collider: ColliderHandle) => boolean,
+ target?: ColliderShapeCastHit,
+ ): ColliderShapeCastHit | null {
+ let rawPos = VectorOps.intoRaw(shapePos);
+ let rawRot = RotationOps.intoRaw(shapeRot);
+ let rawVel = VectorOps.intoRaw(shapeVel);
+ let rawShape = shape.intoRaw();
+
+ const rawColliderShapeCastHit = this.raw.castShape(
+ narrowPhase.raw,
+ bodies.raw,
+ colliders.raw,
+ rawPos,
+ rawRot,
+ rawVel,
+ rawShape,
+ targetDistance,
+ maxToi,
+ stopAtPenetration,
+ filterFlags,
+ filterGroups,
+ filterExcludeCollider,
+ filterExcludeRigidBody,
+ filterPredicate,
+ );
+
+ let result = null;
+ if (rawColliderShapeCastHit) {
+ const colliderHandle: number =
+ rawColliderShapeCastHit.colliderHandle();
+ rawColliderShapeCastHit.getComponents(scratchBuffer);
+ result = ColliderShapeCastHit.fromBuffer(
+ colliders.get(colliderHandle),
+ scratchBuffer,
+ target,
+ );
+ rawColliderShapeCastHit.free();
+ }
+
+ rawPos.free();
+ rawRot.free();
+ rawVel.free();
+ rawShape.free();
+
+ return result;
+ }
+
+ /**
+ * Retrieve all the colliders intersecting the given shape.
+ *
+ * @param colliders - The set of colliders taking part in this pipeline.
+ * @param shapePos - The position of the shape to test.
+ * @param shapeRot - The orientation of the shape to test.
+ * @param shape - The shape to test.
+ * @param groups - The bit groups and filter associated to the shape to test, in order to only
+ * test on colliders with collision groups compatible with this group.
+ * @param callback - A function called with the handles of each collider intersecting the `shape`.
+ */
+ public intersectionsWithShape(
+ narrowPhase: NarrowPhase,
+ bodies: RigidBodySet,
+ colliders: ColliderSet,
+ shapePos: Vector,
+ shapeRot: Rotation,
+ shape: Shape,
+ callback: (handle: ColliderHandle) => boolean,
+ filterFlags?: QueryFilterFlags,
+ filterGroups?: InteractionGroups,
+ filterExcludeCollider?: ColliderHandle,
+ filterExcludeRigidBody?: RigidBodyHandle,
+ filterPredicate?: (collider: ColliderHandle) => boolean,
+ ) {
+ let rawPos = VectorOps.intoRaw(shapePos);
+ let rawRot = RotationOps.intoRaw(shapeRot);
+ let rawShape = shape.intoRaw();
+
+ this.raw.intersectionsWithShape(
+ narrowPhase.raw,
+ bodies.raw,
+ colliders.raw,
+ rawPos,
+ rawRot,
+ rawShape,
+ callback,
+ filterFlags,
+ filterGroups,
+ filterExcludeCollider,
+ filterExcludeRigidBody,
+ filterPredicate,
+ );
+
+ rawPos.free();
+ rawRot.free();
+ rawShape.free();
+ }
+
+ /**
+ * Finds the handles of all the colliders with an AABB intersecting the given AABB.
+ *
+ * @param aabbCenter - The center of the AABB to test.
+ * @param aabbHalfExtents - The half-extents of the AABB to test.
+ * @param callback - The callback that will be called with the handles of all the colliders
+ * currently intersecting the given AABB.
+ */
+ public collidersWithAabbIntersectingAabb(
+ narrowPhase: NarrowPhase,
+ bodies: RigidBodySet,
+ colliders: ColliderSet,
+ aabbCenter: Vector,
+ aabbHalfExtents: Vector,
+ callback: (handle: ColliderHandle) => boolean,
+ ) {
+ let rawCenter = VectorOps.intoRaw(aabbCenter);
+ let rawHalfExtents = VectorOps.intoRaw(aabbHalfExtents);
+ this.raw.collidersWithAabbIntersectingAabb(
+ narrowPhase.raw,
+ bodies.raw,
+ colliders.raw,
+ rawCenter,
+ rawHalfExtents,
+ callback,
+ );
+ rawCenter.free();
+ rawHalfExtents.free();
+ }
+}
diff --git a/typescript/src.ts/geometry/collider.ts b/typescript/src.ts/geometry/collider.ts
new file mode 100644
index 000000000..1f1298fdf
--- /dev/null
+++ b/typescript/src.ts/geometry/collider.ts
@@ -0,0 +1,2193 @@
+import {RawColliderSet, RawShape, RawVHACDParameters} from "../raw";
+import {Rotation, RotationOps, Vector, VectorOps, scratchBuffer} from "../math";
+import {CoefficientCombineRule, RigidBody, RigidBodySet} from "../dynamics";
+import {ActiveHooks, ActiveEvents} from "../pipeline";
+import {InteractionGroups} from "./interaction_groups";
+import {
+ Shape,
+ Cuboid,
+ Ball,
+ ShapeType,
+ Capsule,
+ Voxels,
+ TriMesh,
+ Polyline,
+ Heightfield,
+ Compound,
+ Segment,
+ Triangle,
+ RoundTriangle,
+ RoundCuboid,
+ HalfSpace,
+ TriMeshFlags,
+ // #if DIM2
+ ConvexPolygon,
+ RoundConvexPolygon,
+ // #endif
+ // #if DIM3
+ Cylinder,
+ RoundCylinder,
+ Cone,
+ RoundCone,
+ ConvexPolyhedron,
+ RoundConvexPolyhedron,
+ HeightFieldFlags,
+ // #endif
+} from "./shape";
+import {Ray, RayIntersection} from "./ray";
+import {PointProjection} from "./point";
+import {ColliderShapeCastHit, ShapeCastHit} from "./toi";
+import {ShapeContact} from "./contact";
+import {ColliderSet} from "./collider_set";
+
+/**
+ * Parameters for VHACD convex decomposition algorithm.
+ *
+ * All parameters are optional. When not specified, default values from the
+ * underlying Rapier/Parry library are used.
+ */
+export interface VHACDParameters {
+ /**
+ * Controls the bias toward clipping along symmetry planes.
+ * Range: [0.0, 1.0]
+ */
+ alpha?: number;
+
+ /**
+ * Controls the bias toward clipping along revolution planes.
+ * Range: [0.0, 1.0]
+ * Useful for objects with cylindrical or rotational features.
+ */
+ beta?: number;
+
+ /**
+ * Controls maximum allowed deviation from convexity.
+ * Range: [0.0, 1.0]
+ * Lower values create more convex parts for a tighter fit.
+ */
+ concavity?: number;
+
+ /**
+ * Controls the granularity of searching optimal clipping planes.
+ * Lower values test more planes (slower but more accurate).
+ */
+ planeDownsampling?: number;
+
+ /**
+ * Controls the precision of convex hull generation.
+ * Lower values use more voxels for hull computation.
+ */
+ convexHullDownsampling?: number;
+
+ /**
+ * Maximum number of convex parts to generate.
+ * Limits part count during decomposition.
+ */
+ maxConvexHulls?: number;
+
+ /**
+ * Voxel grid resolution for decomposition.
+ * Higher resolution captures more detail but is slower.
+ */
+ resolution?: number;
+
+ /**
+ * Whether to use approximate convex hulls for better performance.
+ * Faster method with minimal impact on quality.
+ */
+ convexHullApproximation?: boolean;
+}
+
+/**
+ * Flags affecting whether collision-detection happens between two colliders
+ * depending on the type of rigid-bodies they are attached to.
+ */
+export enum ActiveCollisionTypes {
+ /**
+ * Enable collision-detection between a collider attached to a dynamic body
+ * and another collider attached to a dynamic body.
+ */
+ DYNAMIC_DYNAMIC = 0b0000_0000_0000_0001,
+ /**
+ * Enable collision-detection between a collider attached to a dynamic body
+ * and another collider attached to a kinematic body.
+ */
+ DYNAMIC_KINEMATIC = 0b0000_0000_0000_1100,
+ /**
+ * Enable collision-detection between a collider attached to a dynamic body
+ * and another collider attached to a fixed body (or not attached to any body).
+ */
+ DYNAMIC_FIXED = 0b0000_0000_0000_0010,
+ /**
+ * Enable collision-detection between a collider attached to a kinematic body
+ * and another collider attached to a kinematic body.
+ */
+ KINEMATIC_KINEMATIC = 0b1100_1100_0000_0000,
+
+ /**
+ * Enable collision-detection between a collider attached to a kinematic body
+ * and another collider attached to a fixed body (or not attached to any body).
+ */
+ KINEMATIC_FIXED = 0b0010_0010_0000_0000,
+
+ /**
+ * Enable collision-detection between a collider attached to a fixed body (or
+ * not attached to any body) and another collider attached to a fixed body (or
+ * not attached to any body).
+ */
+ FIXED_FIXED = 0b0000_0000_0010_0000,
+ /**
+ * The default active collision types, enabling collisions between a dynamic body
+ * and another body of any type, but not enabling collisions between two non-dynamic bodies.
+ */
+ DEFAULT = DYNAMIC_KINEMATIC | DYNAMIC_DYNAMIC | DYNAMIC_FIXED,
+ /**
+ * Enable collisions between any kind of rigid-bodies (including between two non-dynamic bodies).
+ */
+ ALL = DYNAMIC_KINEMATIC |
+ DYNAMIC_DYNAMIC |
+ DYNAMIC_FIXED |
+ KINEMATIC_KINEMATIC |
+ KINEMATIC_FIXED |
+ KINEMATIC_KINEMATIC,
+}
+
+/**
+ * The integer identifier of a collider added to a `ColliderSet`.
+ */
+export type ColliderHandle = number;
+
+/**
+ * A geometric entity that can be attached to a body so it can be affected
+ * by contacts and proximity queries.
+ */
+export class Collider {
+ private colliderSet: ColliderSet; // The Collider won't need to free this.
+ readonly handle: ColliderHandle;
+ private _shape: Shape; // TODO: deprecate/remove this since it isn’t a reliable way of getting the latest shape properties.
+ private _parent: RigidBody | null;
+
+ constructor(
+ colliderSet: ColliderSet,
+ handle: ColliderHandle,
+ parent: RigidBody | null,
+ shape?: Shape,
+ ) {
+ this.colliderSet = colliderSet;
+ this.handle = handle;
+ this._parent = parent;
+ this._shape = shape;
+ }
+
+ /** @internal */
+ public finalizeDeserialization(bodies: RigidBodySet) {
+ if (this.handle != null) {
+ this._parent = bodies.get(
+ this.colliderSet.raw.coParent(this.handle),
+ );
+ }
+ }
+
+ private ensureShapeIsCached() {
+ if (!this._shape)
+ this._shape = Shape.fromRaw(this.colliderSet.raw, this.handle);
+ }
+
+ /**
+ * The shape of this collider.
+ */
+ public get shape(): Shape {
+ this.ensureShapeIsCached();
+ return this._shape;
+ }
+
+ /**
+ * Set the internal cached JS shape to null.
+ *
+ * This can be useful if you want to free some memory (assuming you are not
+ * holding any other references to the shape object), or in order to force
+ * the recalculation of the JS shape (the next time the `shape` getter is
+ * accessed) from the WASM source of truth.
+ */
+ public clearShapeCache() {
+ this._shape = null;
+ }
+
+ /**
+ * Checks if this collider is still valid (i.e. that it has
+ * not been deleted from the collider set yet).
+ */
+ public isValid(): boolean {
+ return this.colliderSet.raw.contains(this.handle);
+ }
+
+ /**
+ * The world-space translation of this collider.
+ *
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public translation(target?: Vector): Vector {
+ this.colliderSet.raw.coTranslation(this.handle, scratchBuffer);
+ return VectorOps.fromBuffer(scratchBuffer, target);
+ }
+
+ /**
+ * The translation of this collider relative to its parent rigid-body.
+ *
+ * Returns `null` if the collider doesn’t have a parent rigid-body.
+ *
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public translationWrtParent(target?: Vector): Vector | null {
+ const hasParent = this.colliderSet.raw.coTranslationWrtParent(
+ this.handle,
+ scratchBuffer,
+ );
+ return hasParent ? VectorOps.fromBuffer(scratchBuffer, target) : null;
+ }
+
+ // #if DIM2
+ /**
+ * The world-space orientation of this collider.
+ */
+ public rotation(): number {
+ return this.colliderSet.raw.coRotation(this.handle);
+ }
+ // #endif
+
+ // #if DIM3
+ /**
+ * The world-space orientation of this collider.
+ *
+ * @param {Rotation?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public rotation(target?: Rotation): Rotation {
+ this.colliderSet.raw.coRotation(this.handle, scratchBuffer);
+ return RotationOps.fromBuffer(scratchBuffer, target);
+ }
+ // #endif
+
+ // #if DIM2
+ /**
+ * The orientation of this collider relative to its parent rigid-body.
+ *
+ * Returns `null` if the collider doesn’t have a parent rigid-body.
+ */
+ public rotationWrtParent(): Rotation | null {
+ const val = this.colliderSet.raw.coRotationWrtParent(this.handle);
+ return isNaN(val) ? null : val;
+ }
+ // #endif
+
+ // #if DIM3
+ /**
+ * The orientation of this collider relative to its parent rigid-body.
+ *
+ * Returns `null` if the collider doesn’t have a parent rigid-body.
+ *
+ * @param {Rotation?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public rotationWrtParent(target?: Rotation): Rotation | null {
+ const hasParent = this.colliderSet.raw.coRotationWrtParent(
+ this.handle,
+ scratchBuffer,
+ );
+ return hasParent ? RotationOps.fromBuffer(scratchBuffer, target) : null;
+ }
+ // #endif
+
+ /**
+ * Is this collider a sensor?
+ */
+ public isSensor(): boolean {
+ return this.colliderSet.raw.coIsSensor(this.handle);
+ }
+
+ /**
+ * Sets whether this collider is a sensor.
+ * @param isSensor - If `true`, the collider will be a sensor.
+ */
+ public setSensor(isSensor: boolean) {
+ this.colliderSet.raw.coSetSensor(this.handle, isSensor);
+ }
+
+ /**
+ * Sets the new shape of the collider.
+ * @param shape - The collider’s new shape.
+ */
+ public setShape(shape: Shape) {
+ let rawShape = shape.intoRaw();
+ this.colliderSet.raw.coSetShape(this.handle, rawShape);
+ rawShape.free();
+ this._shape = shape;
+ }
+
+ /**
+ * Sets whether this collider is enabled or not.
+ *
+ * @param enabled - Set to `false` to disable this collider (its parent rigid-body won’t be disabled automatically by this).
+ */
+ public setEnabled(enabled: boolean) {
+ this.colliderSet.raw.coSetEnabled(this.handle, enabled);
+ }
+
+ /**
+ * Is this collider enabled?
+ */
+ public isEnabled(): boolean {
+ return this.colliderSet.raw.coIsEnabled(this.handle);
+ }
+
+ /**
+ * Sets the restitution coefficient of the collider to be created.
+ *
+ * @param restitution - The restitution coefficient in `[0, 1]`. A value of 0 (the default) means no bouncing behavior
+ * while 1 means perfect bouncing (though energy may still be lost due to numerical errors of the
+ * constraints solver).
+ */
+ public setRestitution(restitution: number) {
+ this.colliderSet.raw.coSetRestitution(this.handle, restitution);
+ }
+
+ /**
+ * Sets the friction coefficient of the collider to be created.
+ *
+ * @param friction - The friction coefficient. Must be greater or equal to 0. This is generally smaller than 1. The
+ * higher the coefficient, the stronger friction forces will be for contacts with the collider
+ * being built.
+ */
+ public setFriction(friction: number) {
+ this.colliderSet.raw.coSetFriction(this.handle, friction);
+ }
+
+ /**
+ * Gets the rule used to combine the friction coefficients of two colliders
+ * colliders involved in a contact.
+ */
+ public frictionCombineRule(): CoefficientCombineRule {
+ return this.colliderSet.raw.coFrictionCombineRule(this.handle);
+ }
+
+ /**
+ * Sets the rule used to combine the friction coefficients of two colliders
+ * colliders involved in a contact.
+ *
+ * @param rule − The combine rule to apply.
+ */
+ public setFrictionCombineRule(rule: CoefficientCombineRule) {
+ this.colliderSet.raw.coSetFrictionCombineRule(this.handle, rule);
+ }
+
+ /**
+ * Gets the rule used to combine the restitution coefficients of two colliders
+ * colliders involved in a contact.
+ */
+ public restitutionCombineRule(): CoefficientCombineRule {
+ return this.colliderSet.raw.coRestitutionCombineRule(this.handle);
+ }
+
+ /**
+ * Sets the rule used to combine the restitution coefficients of two colliders
+ * colliders involved in a contact.
+ *
+ * @param rule − The combine rule to apply.
+ */
+ public setRestitutionCombineRule(rule: CoefficientCombineRule) {
+ this.colliderSet.raw.coSetRestitutionCombineRule(this.handle, rule);
+ }
+
+ /**
+ * Sets the collision groups used by this collider.
+ *
+ * Two colliders will interact iff. their collision groups are compatible.
+ * See the documentation of `InteractionGroups` for details on the used bit pattern.
+ *
+ * @param groups - The collision groups used for the collider being built.
+ */
+ public setCollisionGroups(groups: InteractionGroups) {
+ this.colliderSet.raw.coSetCollisionGroups(this.handle, groups);
+ }
+
+ /**
+ * Sets the solver groups used by this collider.
+ *
+ * Forces between two colliders in contact will be computed iff their solver
+ * groups are compatible.
+ * See the documentation of `InteractionGroups` for details on the used bit pattern.
+ *
+ * @param groups - The solver groups used for the collider being built.
+ */
+ public setSolverGroups(groups: InteractionGroups) {
+ this.colliderSet.raw.coSetSolverGroups(this.handle, groups);
+ }
+
+ /**
+ * Sets the contact skin for this collider.
+ *
+ * See the documentation of `ColliderDesc.setContactSkin` for additional details.
+ */
+ public contactSkin(): number {
+ return this.colliderSet.raw.coContactSkin(this.handle);
+ }
+
+ /**
+ * Sets the contact skin for this collider.
+ *
+ * See the documentation of `ColliderDesc.setContactSkin` for additional details.
+ *
+ * @param thickness - The contact skin thickness.
+ */
+ public setContactSkin(thickness: number) {
+ return this.colliderSet.raw.coSetContactSkin(this.handle, thickness);
+ }
+
+ /**
+ * Get the physics hooks active for this collider.
+ */
+ public activeHooks(): ActiveHooks {
+ return this.colliderSet.raw.coActiveHooks(this.handle);
+ }
+
+ /**
+ * Set the physics hooks active for this collider.
+ *
+ * Use this to enable custom filtering rules for contact/intersecstion pairs involving this collider.
+ *
+ * @param activeHooks - The hooks active for contact/intersection pairs involving this collider.
+ */
+ public setActiveHooks(activeHooks: ActiveHooks) {
+ this.colliderSet.raw.coSetActiveHooks(this.handle, activeHooks);
+ }
+
+ /**
+ * The events active for this collider.
+ */
+ public activeEvents(): ActiveEvents {
+ return this.colliderSet.raw.coActiveEvents(this.handle);
+ }
+
+ /**
+ * Set the events active for this collider.
+ *
+ * Use this to enable contact and/or intersection event reporting for this collider.
+ *
+ * @param activeEvents - The events active for contact/intersection pairs involving this collider.
+ */
+ public setActiveEvents(activeEvents: ActiveEvents) {
+ this.colliderSet.raw.coSetActiveEvents(this.handle, activeEvents);
+ }
+
+ /**
+ * Gets the collision types active for this collider.
+ */
+ public activeCollisionTypes(): ActiveCollisionTypes {
+ return this.colliderSet.raw.coActiveCollisionTypes(this.handle);
+ }
+
+ /**
+ * Sets the total force magnitude beyond which a contact force event can be emitted.
+ *
+ * @param threshold - The new force threshold.
+ */
+ public setContactForceEventThreshold(threshold: number) {
+ return this.colliderSet.raw.coSetContactForceEventThreshold(
+ this.handle,
+ threshold,
+ );
+ }
+
+ /**
+ * The total force magnitude beyond which a contact force event can be emitted.
+ */
+ public contactForceEventThreshold(): number {
+ return this.colliderSet.raw.coContactForceEventThreshold(this.handle);
+ }
+
+ /**
+ * Set the collision types active for this collider.
+ *
+ * @param activeCollisionTypes - The hooks active for contact/intersection pairs involving this collider.
+ */
+ public setActiveCollisionTypes(activeCollisionTypes: ActiveCollisionTypes) {
+ this.colliderSet.raw.coSetActiveCollisionTypes(
+ this.handle,
+ activeCollisionTypes,
+ );
+ }
+
+ /**
+ * Sets the uniform density of this collider.
+ *
+ * This will override any previous mass-properties set by `this.setDensity`,
+ * `this.setMass`, `this.setMassProperties`, `ColliderDesc.density`,
+ * `ColliderDesc.mass`, or `ColliderDesc.massProperties` for this collider.
+ *
+ * The mass and angular inertia of this collider will be computed automatically based on its
+ * shape.
+ */
+ public setDensity(density: number) {
+ this.colliderSet.raw.coSetDensity(this.handle, density);
+ }
+
+ /**
+ * Sets the mass of this collider.
+ *
+ * This will override any previous mass-properties set by `this.setDensity`,
+ * `this.setMass`, `this.setMassProperties`, `ColliderDesc.density`,
+ * `ColliderDesc.mass`, or `ColliderDesc.massProperties` for this collider.
+ *
+ * The angular inertia of this collider will be computed automatically based on its shape
+ * and this mass value.
+ */
+ public setMass(mass: number) {
+ this.colliderSet.raw.coSetMass(this.handle, mass);
+ }
+
+ // #if DIM3
+ /**
+ * Sets the mass of this collider.
+ *
+ * This will override any previous mass-properties set by `this.setDensity`,
+ * `this.setMass`, `this.setMassProperties`, `ColliderDesc.density`,
+ * `ColliderDesc.mass`, or `ColliderDesc.massProperties` for this collider.
+ */
+ public setMassProperties(
+ mass: number,
+ centerOfMass: Vector,
+ principalAngularInertia: Vector,
+ angularInertiaLocalFrame: Rotation,
+ ) {
+ let rawCom = VectorOps.intoRaw(centerOfMass);
+ let rawPrincipalInertia = VectorOps.intoRaw(principalAngularInertia);
+ let rawInertiaFrame = RotationOps.intoRaw(angularInertiaLocalFrame);
+
+ this.colliderSet.raw.coSetMassProperties(
+ this.handle,
+ mass,
+ rawCom,
+ rawPrincipalInertia,
+ rawInertiaFrame,
+ );
+
+ rawCom.free();
+ rawPrincipalInertia.free();
+ rawInertiaFrame.free();
+ }
+
+ // #endif
+
+ // #if DIM2
+ /**
+ * Sets the mass of this collider.
+ *
+ * This will override any previous mass-properties set by `this.setDensity`,
+ * `this.setMass`, `this.setMassProperties`, `ColliderDesc.density`,
+ * `ColliderDesc.mass`, or `ColliderDesc.massProperties` for this collider.
+ */
+ public setMassProperties(
+ mass: number,
+ centerOfMass: Vector,
+ principalAngularInertia: number,
+ ) {
+ let rawCom = VectorOps.intoRaw(centerOfMass);
+ this.colliderSet.raw.coSetMassProperties(
+ this.handle,
+ mass,
+ rawCom,
+ principalAngularInertia,
+ );
+ rawCom.free();
+ }
+
+ // #endif
+
+ /**
+ * Sets the translation of this collider.
+ *
+ * @param tra - The world-space position of the collider.
+ */
+ public setTranslation(tra: Vector) {
+ // #if DIM2
+ this.colliderSet.raw.coSetTranslation(this.handle, tra.x, tra.y);
+ // #endif
+ // #if DIM3
+ this.colliderSet.raw.coSetTranslation(this.handle, tra.x, tra.y, tra.z);
+ // #endif
+ }
+
+ /**
+ * Sets the translation of this collider relative to its parent rigid-body.
+ *
+ * Does nothing if this collider isn't attached to a rigid-body.
+ *
+ * @param tra - The new translation of the collider relative to its parent.
+ */
+ public setTranslationWrtParent(tra: Vector) {
+ // #if DIM2
+ this.colliderSet.raw.coSetTranslationWrtParent(
+ this.handle,
+ tra.x,
+ tra.y,
+ );
+ // #endif
+ // #if DIM3
+ this.colliderSet.raw.coSetTranslationWrtParent(
+ this.handle,
+ tra.x,
+ tra.y,
+ tra.z,
+ );
+ // #endif
+ }
+
+ // #if DIM3
+ /**
+ * Sets the rotation quaternion of this collider.
+ *
+ * This does nothing if a zero quaternion is provided.
+ *
+ * @param rotation - The rotation to set.
+ */
+ public setRotation(rot: Rotation) {
+ this.colliderSet.raw.coSetRotation(
+ this.handle,
+ rot.x,
+ rot.y,
+ rot.z,
+ rot.w,
+ );
+ }
+
+ /**
+ * Sets the rotation quaternion of this collider relative to its parent rigid-body.
+ *
+ * This does nothing if a zero quaternion is provided or if this collider isn't
+ * attached to a rigid-body.
+ *
+ * @param rotation - The rotation to set.
+ */
+ public setRotationWrtParent(rot: Rotation) {
+ this.colliderSet.raw.coSetRotationWrtParent(
+ this.handle,
+ rot.x,
+ rot.y,
+ rot.z,
+ rot.w,
+ );
+ }
+
+ // #endif
+ // #if DIM2
+ /**
+ * Sets the rotation angle of this collider.
+ *
+ * @param angle - The rotation angle, in radians.
+ */
+ public setRotation(angle: number) {
+ this.colliderSet.raw.coSetRotation(this.handle, angle);
+ }
+
+ /**
+ * Sets the rotation angle of this collider relative to its parent rigid-body.
+ *
+ * Does nothing if this collider isn't attached to a rigid-body.
+ *
+ * @param angle - The rotation angle, in radians.
+ */
+ public setRotationWrtParent(angle: number) {
+ this.colliderSet.raw.coSetRotationWrtParent(this.handle, angle);
+ }
+
+ // #endif
+
+ /**
+ * The type of the shape of this collider.
+ */
+ public shapeType(): ShapeType {
+ return this.colliderSet.raw.coShapeType(
+ this.handle,
+ ) as number as ShapeType;
+ }
+
+ /**
+ * The half-extents of this collider if it is a cuboid shape.
+ *
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public halfExtents(target?: Vector): Vector | null {
+ const isCuboid = this.colliderSet.raw.coHalfExtents(
+ this.handle,
+ scratchBuffer,
+ );
+ return isCuboid ? VectorOps.fromBuffer(scratchBuffer, target) : null;
+ }
+
+ /**
+ * Sets the half-extents of this collider if it is a cuboid shape.
+ *
+ * @param newHalfExtents - desired half extents.
+ */
+ public setHalfExtents(newHalfExtents: Vector) {
+ const rawPoint = VectorOps.intoRaw(newHalfExtents);
+ this.colliderSet.raw.coSetHalfExtents(this.handle, rawPoint);
+ }
+
+ /**
+ * The radius of this collider if it is a ball, cylinder, capsule, or cone shape.
+ */
+ public radius(): number {
+ return this.colliderSet.raw.coRadius(this.handle);
+ }
+
+ /**
+ * Sets the radius of this collider if it is a ball, cylinder, capsule, or cone shape.
+ *
+ * @param newRadius - desired radius.
+ */
+ public setRadius(newRadius: number): void {
+ this.colliderSet.raw.coSetRadius(this.handle, newRadius);
+ }
+
+ /**
+ * The radius of the round edges of this collider if it is a round cylinder.
+ */
+ public roundRadius(): number {
+ return this.colliderSet.raw.coRoundRadius(this.handle);
+ }
+
+ /**
+ * Sets the radius of the round edges of this collider if it has round edges.
+ *
+ * @param newBorderRadius - desired round edge radius.
+ */
+ public setRoundRadius(newBorderRadius: number) {
+ this.colliderSet.raw.coSetRoundRadius(this.handle, newBorderRadius);
+ }
+
+ /**
+ * The half height of this collider if it is a cylinder, capsule, or cone shape.
+ */
+ public halfHeight(): number {
+ return this.colliderSet.raw.coHalfHeight(this.handle);
+ }
+
+ /**
+ * Sets the half height of this collider if it is a cylinder, capsule, or cone shape.
+ *
+ * @param newHalfheight - desired half height.
+ */
+ public setHalfHeight(newHalfheight: number) {
+ this.colliderSet.raw.coSetHalfHeight(this.handle, newHalfheight);
+ }
+
+ /**
+ * If this collider has a Voxels shape, this will mark the voxel at the
+ * given grid coordinates as filled or empty (depending on the `filled`
+ * argument).
+ *
+ * Each input value is assumed to be an integer.
+ *
+ * The operation is O(1), unless the provided coordinates are out of the
+ * bounds of the currently allocated internal grid in which case the grid
+ * will be grown automatically.
+ */
+ public setVoxel(
+ ix: number,
+ iy: number,
+ // #if DIM3
+ iz: number,
+ // #endif
+ filled: boolean,
+ ) {
+ this.colliderSet.raw.coSetVoxel(
+ this.handle,
+ ix,
+ iy,
+ // #if DIM3
+ iz,
+ // #endif
+ filled,
+ );
+ // We modified the shape, invalidate it to keep our cache
+ // up-to-date the next time the user requests the shape data.
+ // PERF: this isn’t ideal for performances as this adds a
+ // hidden, non-constant, cost.
+ this._shape = null;
+ }
+
+ /**
+ * If this and `voxels2` are voxel colliders, and a voxel from `this` was
+ * modified with `setVoxel`, this will ensure that a
+ * moving object transitioning across the boundaries of these colliders
+ * won’t suffer from the "internal edges" artifact.
+ *
+ * The indices `ix, iy, iz` indicate the integer coordinates of the voxel in
+ * the local coordinate frame of `this`.
+ *
+ * If the voxels in `voxels2` live in a different coordinate space from `this`,
+ * then the `shift_*` argument indicate the distance, in voxel units, between
+ * the origin of `this` to the origin of `voxels2`.
+ *
+ * This method is intended to be called between `this` and all the other
+ * voxels colliders with a domain intersecting `this` or sharing a domain
+ * boundary. This is an incremental maintenance of the effect of
+ * `combineVoxelStates`.
+ */
+ public propagateVoxelChange(
+ voxels2: Collider,
+ ix: number,
+ iy: number,
+ // #if DIM3
+ iz: number,
+ // #endif
+ shift_x: number,
+ shift_y: number,
+ // #if DIM3
+ shift_z: number,
+ // #endif
+ ) {
+ this.colliderSet.raw.coPropagateVoxelChange(
+ this.handle,
+ voxels2.handle,
+ ix,
+ iy,
+ // #if DIM3
+ iz,
+ // #endif
+ shift_x,
+ shift_y,
+ // #if DIM3
+ shift_z,
+ // #endif
+ );
+ // We modified the shape, invalidate it to keep our cache
+ // up-to-date the next time the user requests the shape data.
+ // PERF: this isn’t ideal for performances as this adds a
+ // hidden, non-constant, cost.
+ this._shape = null;
+ }
+
+ /**
+ * If this and `voxels2` are voxel colliders, this will ensure that a
+ * moving object transitioning across the boundaries of these colliders
+ * won’t suffer from the "internal edges" artifact.
+ *
+ * If the voxels in `voxels2` live in a different coordinate space from `this`,
+ * then the `shift_*` argument indicate the distance, in voxel units, between
+ * the origin of `this` to the origin of `voxels2`.
+ *
+ * This method is intended to be called once between all pairs of voxels
+ * colliders with intersecting domains or shared boundaries.
+ *
+ * If either voxels collider is then modified with `setVoxel`, the
+ * `propagateVoxelChange` method must be called to maintain the coupling
+ * between the voxels shapes after the modification.
+ */
+ public combineVoxelStates(
+ voxels2: Collider,
+ shift_x: number,
+ shift_y: number,
+ // #if DIM3
+ shift_z: number,
+ // #endif
+ ) {
+ this.colliderSet.raw.coCombineVoxelStates(
+ this.handle,
+ voxels2.handle,
+ shift_x,
+ shift_y,
+ // #if DIM3
+ shift_z,
+ // #endif
+ );
+ // We modified the shape, invalidate it to keep our cache
+ // up-to-date the next time the user requests the shape data.
+ // PERF: this isn’t ideal for performances as this adds a
+ // hidden, non-constant, cost.
+ this._shape = null;
+ }
+
+ /**
+ * If this collider has a triangle mesh, polyline, convex polygon, or convex polyhedron shape,
+ * this returns the vertex buffer of said shape.
+ */
+ public vertices(): Float32Array {
+ return this.colliderSet.raw.coVertices(this.handle);
+ }
+
+ /**
+ * If this collider has a triangle mesh, polyline, or convex polyhedron shape,
+ * this returns the index buffer of said shape.
+ */
+ public indices(): Uint32Array | undefined {
+ return this.colliderSet.raw.coIndices(this.handle);
+ }
+
+ /**
+ * If this collider has a heightfield shape, this returns the heights buffer of
+ * the heightfield.
+ * In 3D, the returned height matrix is provided in column-major order.
+ */
+ public heightfieldHeights(): Float32Array {
+ return this.colliderSet.raw.coHeightfieldHeights(this.handle);
+ }
+
+ /**
+ * If this collider has a heightfield shape, this returns the scale
+ * applied to it.
+ *
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public heightfieldScale(target?: Vector): Vector | null {
+ const isHeightfield = this.colliderSet.raw.coHeightfieldScale(
+ this.handle,
+ scratchBuffer,
+ );
+ return isHeightfield
+ ? VectorOps.fromBuffer(scratchBuffer, target)
+ : null;
+ }
+
+ // #if DIM3
+ /**
+ * If this collider has a heightfield shape, this returns the number of
+ * rows of its height matrix.
+ */
+ public heightfieldNRows(): number {
+ return this.colliderSet.raw.coHeightfieldNRows(this.handle);
+ }
+
+ /**
+ * If this collider has a heightfield shape, this returns the number of
+ * columns of its height matrix.
+ */
+ public heightfieldNCols(): number {
+ return this.colliderSet.raw.coHeightfieldNCols(this.handle);
+ }
+
+ // #endif
+
+ /**
+ * The rigid-body this collider is attached to.
+ */
+ public parent(): RigidBody | null {
+ return this._parent;
+ }
+
+ /**
+ * The friction coefficient of this collider.
+ */
+ public friction(): number {
+ return this.colliderSet.raw.coFriction(this.handle);
+ }
+
+ /**
+ * The restitution coefficient of this collider.
+ */
+ public restitution(): number {
+ return this.colliderSet.raw.coRestitution(this.handle);
+ }
+
+ /**
+ * The density of this collider.
+ */
+ public density(): number {
+ return this.colliderSet.raw.coDensity(this.handle);
+ }
+
+ /**
+ * The mass of this collider.
+ */
+ public mass(): number {
+ return this.colliderSet.raw.coMass(this.handle);
+ }
+
+ /**
+ * The volume of this collider.
+ */
+ public volume(): number {
+ return this.colliderSet.raw.coVolume(this.handle);
+ }
+
+ /**
+ * The collision groups of this collider.
+ */
+ public collisionGroups(): InteractionGroups {
+ return this.colliderSet.raw.coCollisionGroups(this.handle);
+ }
+
+ /**
+ * The solver groups of this collider.
+ */
+ public solverGroups(): InteractionGroups {
+ return this.colliderSet.raw.coSolverGroups(this.handle);
+ }
+
+ /**
+ * Tests if this collider contains a point.
+ *
+ * @param point - The point to test.
+ */
+ public containsPoint(point: Vector): boolean {
+ let rawPoint = VectorOps.intoRaw(point);
+ let result = this.colliderSet.raw.coContainsPoint(
+ this.handle,
+ rawPoint,
+ );
+
+ rawPoint.free();
+
+ return result;
+ }
+
+ /**
+ * Find the projection of a point on this collider.
+ *
+ * @param point - The point to project.
+ * @param solid - If this is set to `true` then the collider shapes are considered to
+ * be plain (if the point is located inside of a plain shape, its projection is the point
+ * itself). If it is set to `false` the collider shapes are considered to be hollow
+ * (if the point is located inside of an hollow shape, it is projected on the shape's
+ * boundary).
+ */
+ public projectPoint(
+ point: Vector,
+ solid: boolean,
+ target?: PointProjection,
+ ): PointProjection | null {
+ let rawPoint = VectorOps.intoRaw(point);
+ let result = PointProjection.fromBuffer(
+ this.colliderSet.raw.coProjectPoint(this.handle, rawPoint, solid),
+ target,
+ );
+
+ rawPoint.free();
+
+ return result;
+ }
+
+ /**
+ * Tests if this collider intersects the given ray.
+ *
+ * @param ray - The ray to cast.
+ * @param maxToi - The maximum time-of-impact that can be reported by this cast. This effectively
+ * limits the length of the ray to `ray.dir.norm() * maxToi`.
+ */
+ public intersectsRay(ray: Ray, maxToi: number): boolean {
+ let rawOrig = VectorOps.intoRaw(ray.origin);
+ let rawDir = VectorOps.intoRaw(ray.dir);
+ let result = this.colliderSet.raw.coIntersectsRay(
+ this.handle,
+ rawOrig,
+ rawDir,
+ maxToi,
+ );
+
+ rawOrig.free();
+ rawDir.free();
+
+ return result;
+ }
+
+ /**
+ * Computes the smallest time between this and the given shape under translational movement are separated by a distance smaller or equal to distance.
+ *
+ * @param collider1Vel - The constant velocity of the current shape to cast (i.e. the cast direction).
+ * @param shape2 - The shape to cast against.
+ * @param shape2Pos - The position of the second shape.
+ * @param shape2Rot - The rotation of the second shape.
+ * @param shape2Vel - The constant velocity of the second shape.
+ * @param targetDistance − If the shape moves closer to this distance from a collider, a hit
+ * will be returned.
+ * @param maxToi - The maximum time-of-impact that can be reported by this cast. This effectively
+ * limits the distance traveled by the shape to `collider1Vel.norm() * maxToi`.
+ * @param stopAtPenetration - If set to `false`, the linear shape-cast won’t immediately stop if
+ * the shape is penetrating another shape at its starting point **and** its trajectory is such
+ * that it’s on a path to exit that penetration state.
+ * @param {ShapeCastHit?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public castShape(
+ collider1Vel: Vector,
+ shape2: Shape,
+ shape2Pos: Vector,
+ shape2Rot: Rotation,
+ shape2Vel: Vector,
+ targetDistance: number,
+ maxToi: number,
+ stopAtPenetration: boolean,
+ target?: ShapeCastHit,
+ ): ShapeCastHit | null {
+ let rawCollider1Vel = VectorOps.intoRaw(collider1Vel);
+ let rawShape2Pos = VectorOps.intoRaw(shape2Pos);
+ let rawShape2Rot = RotationOps.intoRaw(shape2Rot);
+ let rawShape2Vel = VectorOps.intoRaw(shape2Vel);
+ let rawShape2 = shape2.intoRaw();
+
+ const rawShapeCastHit = this.colliderSet.raw.coCastShape(
+ this.handle,
+ rawCollider1Vel,
+ rawShape2,
+ rawShape2Pos,
+ rawShape2Rot,
+ rawShape2Vel,
+ targetDistance,
+ maxToi,
+ stopAtPenetration,
+ );
+
+ let result = null;
+ if (rawShapeCastHit) {
+ rawShapeCastHit.getComponents(scratchBuffer);
+ result = ShapeCastHit.fromBuffer(null, scratchBuffer, target);
+ rawShapeCastHit.free();
+ }
+
+ rawCollider1Vel.free();
+ rawShape2Pos.free();
+ rawShape2Rot.free();
+ rawShape2Vel.free();
+ rawShape2.free();
+
+ return result;
+ }
+
+ /**
+ * Computes the smallest time between this and the given collider under translational movement are separated by a distance smaller or equal to distance.
+ *
+ * @param collider1Vel - The constant velocity of the current collider to cast (i.e. the cast direction).
+ * @param collider2 - The collider to cast against.
+ * @param collider2Vel - The constant velocity of the second collider.
+ * @param targetDistance − If the shape moves closer to this distance from a collider, a hit
+ * will be returned.
+ * @param maxToi - The maximum time-of-impact that can be reported by this cast. This effectively
+ * limits the distance traveled by the shape to `shapeVel.norm() * maxToi`.
+ * @param stopAtPenetration - If set to `false`, the linear shape-cast won’t immediately stop if
+ * the shape is penetrating another shape at its starting point **and** its trajectory is such
+ * that it’s on a path to exit that penetration state.
+ * @param {ColliderShapeCastHit?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public castCollider(
+ collider1Vel: Vector,
+ collider2: Collider,
+ collider2Vel: Vector,
+ targetDistance: number,
+ maxToi: number,
+ stopAtPenetration: boolean,
+ target?: ColliderShapeCastHit,
+ ): ColliderShapeCastHit | null {
+ let rawCollider1Vel = VectorOps.intoRaw(collider1Vel);
+ let rawCollider2Vel = VectorOps.intoRaw(collider2Vel);
+
+ const rawColliderShapeCastHit = this.colliderSet.raw.coCastCollider(
+ this.handle,
+ rawCollider1Vel,
+ collider2.handle,
+ rawCollider2Vel,
+ targetDistance,
+ maxToi,
+ stopAtPenetration,
+ );
+
+ let result = null;
+ if (rawColliderShapeCastHit) {
+ const colliderHandle: number =
+ rawColliderShapeCastHit.colliderHandle();
+ rawColliderShapeCastHit.getComponents(scratchBuffer);
+ result = ColliderShapeCastHit.fromBuffer(
+ this.colliderSet.get(colliderHandle),
+ scratchBuffer,
+ target,
+ );
+ rawColliderShapeCastHit.free();
+ }
+
+ rawCollider1Vel.free();
+ rawCollider2Vel.free();
+
+ return result;
+ }
+
+ public intersectsShape(
+ shape2: Shape,
+ shapePos2: Vector,
+ shapeRot2: Rotation,
+ ): boolean {
+ let rawPos2 = VectorOps.intoRaw(shapePos2);
+ let rawRot2 = RotationOps.intoRaw(shapeRot2);
+ let rawShape2 = shape2.intoRaw();
+
+ let result = this.colliderSet.raw.coIntersectsShape(
+ this.handle,
+ rawShape2,
+ rawPos2,
+ rawRot2,
+ );
+
+ rawPos2.free();
+ rawRot2.free();
+ rawShape2.free();
+
+ return result;
+ }
+
+ /**
+ * Computes one pair of contact points between the shape owned by this collider and the given shape.
+ *
+ * @param shape2 - The second shape.
+ * @param shape2Pos - The initial position of the second shape.
+ * @param shape2Rot - The rotation of the second shape.
+ * @param prediction - The prediction value, if the shapes are separated by a distance greater than this value, test will fail.
+ * @returns `null` if the shapes are separated by a distance greater than prediction, otherwise contact details. The result is given in world-space.
+ */
+ contactShape(
+ shape2: Shape,
+ shape2Pos: Vector,
+ shape2Rot: Rotation,
+ prediction: number,
+ target?: ShapeContact,
+ ): ShapeContact | null {
+ let rawPos2 = VectorOps.intoRaw(shape2Pos);
+ let rawRot2 = RotationOps.intoRaw(shape2Rot);
+ let rawShape2 = shape2.intoRaw();
+
+ let result = ShapeContact.fromBuffer(
+ this.colliderSet.raw.coContactShape(
+ this.handle,
+ rawShape2,
+ rawPos2,
+ rawRot2,
+ prediction,
+ ),
+ target,
+ );
+
+ rawPos2.free();
+ rawRot2.free();
+ rawShape2.free();
+
+ return result;
+ }
+
+ /**
+ * Computes one pair of contact points between the collider and the given collider.
+ *
+ * @param collider2 - The second collider.
+ * @param prediction - The prediction value, if the shapes are separated by a distance greater than this value, test will fail.
+ * @returns `null` if the shapes are separated by a distance greater than prediction, otherwise contact details. The result is given in world-space.
+ */
+ contactCollider(
+ collider2: Collider,
+ prediction: number,
+ target?: ShapeContact,
+ ): ShapeContact | null {
+ let result = ShapeContact.fromBuffer(
+ this.colliderSet.raw.coContactCollider(
+ this.handle,
+ collider2.handle,
+ prediction,
+ ),
+ target,
+ );
+
+ return result;
+ }
+
+ /**
+ * Find the closest intersection between a ray and this collider.
+ *
+ * This also computes the normal at the hit point.
+ * @param ray - The ray to cast.
+ * @param maxToi - The maximum time-of-impact that can be reported by this cast. This effectively
+ * limits the length of the ray to `ray.dir.norm() * maxToi`.
+ * @param solid - If `false` then the ray will attempt to hit the boundary of a shape, even if its
+ * origin already lies inside of a shape. In other terms, `true` implies that all shapes are plain,
+ * whereas `false` implies that all shapes are hollow for this ray-cast.
+ * @returns The time-of-impact between this collider and the ray, or `-1` if there is no intersection.
+ */
+ public castRay(ray: Ray, maxToi: number, solid: boolean): number {
+ let rawOrig = VectorOps.intoRaw(ray.origin);
+ let rawDir = VectorOps.intoRaw(ray.dir);
+ let result = this.colliderSet.raw.coCastRay(
+ this.handle,
+ rawOrig,
+ rawDir,
+ maxToi,
+ solid,
+ );
+
+ rawOrig.free();
+ rawDir.free();
+
+ return result;
+ }
+
+ /**
+ * Find the closest intersection between a ray and this collider.
+ *
+ * This also computes the normal at the hit point.
+ * @param ray - The ray to cast.
+ * @param maxToi - The maximum time-of-impact that can be reported by this cast. This effectively
+ * limits the length of the ray to `ray.dir.norm() * maxToi`.
+ * @param solid - If `false` then the ray will attempt to hit the boundary of a shape, even if its
+ * origin already lies inside of a shape. In other terms, `true` implies that all shapes are plain,
+ * whereas `false` implies that all shapes are hollow for this ray-cast.
+ */
+ public castRayAndGetNormal(
+ ray: Ray,
+ maxToi: number,
+ solid: boolean,
+ target?: RayIntersection,
+ ): RayIntersection | null {
+ let rawOrig = VectorOps.intoRaw(ray.origin);
+ let rawDir = VectorOps.intoRaw(ray.dir);
+ let result = RayIntersection.fromBuffer(
+ this.colliderSet.raw.coCastRayAndGetNormal(
+ this.handle,
+ rawOrig,
+ rawDir,
+ maxToi,
+ solid,
+ ),
+ target,
+ );
+
+ rawOrig.free();
+ rawDir.free();
+
+ return result;
+ }
+}
+
+export enum MassPropsMode {
+ Density,
+ Mass,
+ MassProps,
+}
+
+export class ColliderDesc {
+ enabled: boolean;
+ shape: Shape;
+ massPropsMode: MassPropsMode;
+ mass: number;
+ centerOfMass: Vector;
+ // #if DIM2
+ principalAngularInertia: number;
+ rotationsEnabled: boolean;
+ // #endif
+ // #if DIM3
+ principalAngularInertia: Vector;
+ angularInertiaLocalFrame: Rotation;
+ // #endif
+ density: number;
+ friction: number;
+ restitution: number;
+ rotation: Rotation;
+ translation: Vector;
+ isSensor: boolean;
+ collisionGroups: InteractionGroups;
+ solverGroups: InteractionGroups;
+ frictionCombineRule: CoefficientCombineRule;
+ restitutionCombineRule: CoefficientCombineRule;
+ activeEvents: ActiveEvents;
+ activeHooks: ActiveHooks;
+ activeCollisionTypes: ActiveCollisionTypes;
+ contactForceEventThreshold: number;
+ contactSkin: number;
+
+ /**
+ * Initializes a collider descriptor from the collision shape.
+ *
+ * @param shape - The shape of the collider being built.
+ */
+ constructor(shape: Shape) {
+ this.enabled = true;
+ this.shape = shape;
+ this.massPropsMode = MassPropsMode.Density;
+ this.density = 1.0;
+ this.friction = 0.5;
+ this.restitution = 0.0;
+ this.rotation = RotationOps.identity();
+ this.translation = VectorOps.zeros();
+ this.isSensor = false;
+ this.collisionGroups = 0xffff_ffff;
+ this.solverGroups = 0xffff_ffff;
+ this.frictionCombineRule = CoefficientCombineRule.Average;
+ this.restitutionCombineRule = CoefficientCombineRule.Average;
+ this.activeCollisionTypes = ActiveCollisionTypes.DEFAULT;
+ this.activeEvents = ActiveEvents.NONE;
+ this.activeHooks = ActiveHooks.NONE;
+ this.mass = 0.0;
+ this.centerOfMass = VectorOps.zeros();
+ this.contactForceEventThreshold = 0.0;
+ this.contactSkin = 0.0;
+
+ // #if DIM2
+ this.principalAngularInertia = 0.0;
+ this.rotationsEnabled = true;
+ // #endif
+ // #if DIM3
+ this.principalAngularInertia = VectorOps.zeros();
+ this.angularInertiaLocalFrame = RotationOps.identity();
+ // #endif
+ }
+
+ /**
+ * Create a new collider descriptor with a ball shape.
+ *
+ * @param radius - The radius of the ball.
+ */
+ public static ball(radius: number): ColliderDesc {
+ const shape = new Ball(radius);
+ return new ColliderDesc(shape);
+ }
+
+ /**
+ * Create a new collider descriptor with a capsule shape.
+ *
+ * @param halfHeight - The half-height of the capsule, along the `y` axis.
+ * @param radius - The radius of the capsule basis.
+ */
+ public static capsule(halfHeight: number, radius: number): ColliderDesc {
+ const shape = new Capsule(halfHeight, radius);
+ return new ColliderDesc(shape);
+ }
+
+ /**
+ * Creates a new segment shape.
+ *
+ * @param a - The first point of the segment.
+ * @param b - The second point of the segment.
+ */
+ public static segment(a: Vector, b: Vector): ColliderDesc {
+ const shape = new Segment(a, b);
+ return new ColliderDesc(shape);
+ }
+
+ /**
+ * Creates a new triangle shape.
+ *
+ * @param a - The first point of the triangle.
+ * @param b - The second point of the triangle.
+ * @param c - The third point of the triangle.
+ */
+ public static triangle(a: Vector, b: Vector, c: Vector): ColliderDesc {
+ const shape = new Triangle(a, b, c);
+ return new ColliderDesc(shape);
+ }
+
+ /**
+ * Creates a new triangle shape with round corners.
+ *
+ * @param a - The first point of the triangle.
+ * @param b - The second point of the triangle.
+ * @param c - The third point of the triangle.
+ * @param borderRadius - The radius of the borders of this triangle. In 3D,
+ * this is also equal to half the thickness of the triangle.
+ */
+ public static roundTriangle(
+ a: Vector,
+ b: Vector,
+ c: Vector,
+ borderRadius: number,
+ ): ColliderDesc {
+ const shape = new RoundTriangle(a, b, c, borderRadius);
+ return new ColliderDesc(shape);
+ }
+
+ /**
+ * Creates a new collider descriptor with a polyline shape.
+ *
+ * @param vertices - The coordinates of the polyline's vertices.
+ * @param indices - The indices of the polyline's segments. If this is `undefined` or `null`,
+ * the vertices are assumed to describe a line strip.
+ */
+ public static polyline(
+ vertices: Float32Array,
+ indices?: Uint32Array | null,
+ ): ColliderDesc {
+ const shape = new Polyline(vertices, indices);
+ return new ColliderDesc(shape);
+ }
+
+ /**
+ * Creates a new collider descriptor with a shape made of voxels.
+ *
+ * @param data - Defines the set of voxels. If this is a `Int32Array` then
+ * each voxel is defined from its (signed) grid coordinates,
+ * with 3 (resp 2) contiguous integers per voxel in 3D (resp 2D).
+ * If this is a `Float32Array`, each voxel will be such that
+ * they contain at least one point from this array (where each
+ * point is defined from 3 (resp 2) contiguous numbers per point
+ * in 3D (resp 2D).
+ * @param voxelSize - The size of each voxel.
+ */
+ public static voxels(
+ voxels: Float32Array | Int32Array,
+ voxelSize: Vector,
+ ): ColliderDesc {
+ const shape = new Voxels(voxels, voxelSize);
+ return new ColliderDesc(shape);
+ }
+
+ /**
+ * Creates a new collider descriptor with a triangle mesh shape.
+ *
+ * @param vertices - The coordinates of the triangle mesh's vertices.
+ * @param indices - The indices of the triangle mesh's triangles.
+ */
+ public static trimesh(
+ vertices: Float32Array,
+ indices: Uint32Array,
+ flags?: TriMeshFlags,
+ ): ColliderDesc {
+ const shape = new TriMesh(vertices, indices, flags);
+ return new ColliderDesc(shape);
+ }
+
+ // #if DIM2
+ /**
+ * Creates a new collider descriptor with a rectangular shape.
+ *
+ * @param hx - The half-width of the rectangle along its local `x` axis.
+ * @param hy - The half-width of the rectangle along its local `y` axis.
+ */
+ public static cuboid(hx: number, hy: number): ColliderDesc {
+ const shape = new Cuboid(hx, hy);
+ return new ColliderDesc(shape);
+ }
+
+ /**
+ * Creates a new collider descriptor with a rectangular shape with round borders.
+ *
+ * @param hx - The half-width of the rectangle along its local `x` axis.
+ * @param hy - The half-width of the rectangle along its local `y` axis.
+ * @param borderRadius - The radius of the cuboid's borders.
+ */
+ public static roundCuboid(
+ hx: number,
+ hy: number,
+ borderRadius: number,
+ ): ColliderDesc {
+ const shape = new RoundCuboid(hx, hy, borderRadius);
+ return new ColliderDesc(shape);
+ }
+
+ /**
+ * Creates a new collider description with a halfspace (infinite plane) shape.
+ *
+ * @param normal - The outward normal of the plane.
+ */
+ public static halfspace(normal: Vector): ColliderDesc {
+ const shape = new HalfSpace(normal);
+ return new ColliderDesc(shape);
+ }
+
+ /**
+ * Creates a new collider descriptor with a heightfield shape.
+ *
+ * @param heights - The heights of the heightfield, along its local `y` axis.
+ * @param scale - The scale factor applied to the heightfield.
+ */
+ public static heightfield(
+ heights: Float32Array,
+ scale: Vector,
+ ): ColliderDesc {
+ const shape = new Heightfield(heights, scale);
+ return new ColliderDesc(shape);
+ }
+
+ /**
+ * Computes the convex-hull of the given points and use the resulting
+ * convex polygon as the shape for this new collider descriptor.
+ *
+ * @param points - The point that will be used to compute the convex-hull.
+ */
+ public static convexHull(points: Float32Array): ColliderDesc | null {
+ const shape = new ConvexPolygon(points, false);
+ return new ColliderDesc(shape);
+ }
+
+ /**
+ * Creates a new collider descriptor that uses the given set of points assumed
+ * to form a convex polyline (no convex-hull computation will be done).
+ *
+ * @param vertices - The vertices of the convex polyline.
+ */
+ public static convexPolyline(vertices: Float32Array): ColliderDesc | null {
+ const shape = new ConvexPolygon(vertices, true);
+ return new ColliderDesc(shape);
+ }
+
+ /**
+ * Computes the convex-hull of the given points and use the resulting
+ * convex polygon as the shape for this new collider descriptor. A
+ * border is added to that convex polygon to give it round corners.
+ *
+ * @param points - The point that will be used to compute the convex-hull.
+ * @param borderRadius - The radius of the round border added to the convex polygon.
+ */
+ public static roundConvexHull(
+ points: Float32Array,
+ borderRadius: number,
+ ): ColliderDesc | null {
+ const shape = new RoundConvexPolygon(points, borderRadius, false);
+ return new ColliderDesc(shape);
+ }
+
+ /**
+ * Creates a new collider descriptor that uses the given set of points assumed
+ * to form a round convex polyline (no convex-hull computation will be done).
+ *
+ * @param vertices - The vertices of the convex polyline.
+ * @param borderRadius - The radius of the round border added to the convex polyline.
+ */
+ public static roundConvexPolyline(
+ vertices: Float32Array,
+ borderRadius: number,
+ ): ColliderDesc | null {
+ const shape = new RoundConvexPolygon(vertices, borderRadius, true);
+ return new ColliderDesc(shape);
+ }
+
+ // #endif
+
+ // #if DIM3
+ /**
+ * Creates a new collider descriptor with a cuboid shape.
+ *
+ * @param hx - The half-width of the rectangle along its local `x` axis.
+ * @param hy - The half-width of the rectangle along its local `y` axis.
+ * @param hz - The half-width of the rectangle along its local `z` axis.
+ */
+ public static cuboid(hx: number, hy: number, hz: number): ColliderDesc {
+ const shape = new Cuboid(hx, hy, hz);
+ return new ColliderDesc(shape);
+ }
+
+ /**
+ * Creates a new collider descriptor with a rectangular shape with round borders.
+ *
+ * @param hx - The half-width of the rectangle along its local `x` axis.
+ * @param hy - The half-width of the rectangle along its local `y` axis.
+ * @param hz - The half-width of the rectangle along its local `z` axis.
+ * @param borderRadius - The radius of the cuboid's borders.
+ */
+ public static roundCuboid(
+ hx: number,
+ hy: number,
+ hz: number,
+ borderRadius: number,
+ ): ColliderDesc {
+ const shape = new RoundCuboid(hx, hy, hz, borderRadius);
+ return new ColliderDesc(shape);
+ }
+
+ /**
+ * Creates a new collider descriptor with a heightfield shape.
+ *
+ * @param nrows − The number of rows in the heights matrix.
+ * @param ncols - The number of columns in the heights matrix.
+ * @param heights - The heights of the heightfield along its local `y` axis,
+ * provided as a matrix stored in column-major order.
+ * @param scale - The scale factor applied to the heightfield.
+ */
+ public static heightfield(
+ nrows: number,
+ ncols: number,
+ heights: Float32Array,
+ scale: Vector,
+ flags?: HeightFieldFlags,
+ ): ColliderDesc {
+ const shape = new Heightfield(nrows, ncols, heights, scale, flags);
+ return new ColliderDesc(shape);
+ }
+
+ /**
+ * Create a new collider descriptor with a cylinder shape.
+ *
+ * @param halfHeight - The half-height of the cylinder, along the `y` axis.
+ * @param radius - The radius of the cylinder basis.
+ */
+ public static cylinder(halfHeight: number, radius: number): ColliderDesc {
+ const shape = new Cylinder(halfHeight, radius);
+ return new ColliderDesc(shape);
+ }
+
+ /**
+ * Create a new collider descriptor with a cylinder shape with rounded corners.
+ *
+ * @param halfHeight - The half-height of the cylinder, along the `y` axis.
+ * @param radius - The radius of the cylinder basis.
+ * @param borderRadius - The radius of the cylinder's rounded edges and vertices.
+ */
+ public static roundCylinder(
+ halfHeight: number,
+ radius: number,
+ borderRadius: number,
+ ): ColliderDesc {
+ const shape = new RoundCylinder(halfHeight, radius, borderRadius);
+ return new ColliderDesc(shape);
+ }
+
+ /**
+ * Create a new collider descriptor with a cone shape.
+ *
+ * @param halfHeight - The half-height of the cone, along the `y` axis.
+ * @param radius - The radius of the cone basis.
+ */
+ public static cone(halfHeight: number, radius: number): ColliderDesc {
+ const shape = new Cone(halfHeight, radius);
+ return new ColliderDesc(shape);
+ }
+
+ /**
+ * Create a new collider descriptor with a cone shape with rounded corners.
+ *
+ * @param halfHeight - The half-height of the cone, along the `y` axis.
+ * @param radius - The radius of the cone basis.
+ * @param borderRadius - The radius of the cone's rounded edges and vertices.
+ */
+ public static roundCone(
+ halfHeight: number,
+ radius: number,
+ borderRadius: number,
+ ): ColliderDesc {
+ const shape = new RoundCone(halfHeight, radius, borderRadius);
+ return new ColliderDesc(shape);
+ }
+
+ /**
+ * Computes the convex-hull of the given points and use the resulting
+ * convex polyhedron as the shape for this new collider descriptor.
+ *
+ * @param points - The point that will be used to compute the convex-hull.
+ */
+ public static convexHull(points: Float32Array): ColliderDesc | null {
+ const shape = new ConvexPolyhedron(points, null);
+ return new ColliderDesc(shape);
+ }
+
+ /**
+ * Creates a new collider descriptor that uses the given set of points assumed
+ * to form a convex polyline (no convex-hull computation will be done).
+ *
+ * @param vertices - The vertices of the convex polyline.
+ */
+ public static convexMesh(
+ vertices: Float32Array,
+ indices?: Uint32Array | null,
+ ): ColliderDesc | null {
+ const shape = new ConvexPolyhedron(vertices, indices);
+ return new ColliderDesc(shape);
+ }
+
+ /**
+ * Computes the convex-hull of the given points and use the resulting
+ * convex polyhedron as the shape for this new collider descriptor. A
+ * border is added to that convex polyhedron to give it round corners.
+ *
+ * @param points - The point that will be used to compute the convex-hull.
+ * @param borderRadius - The radius of the round border added to the convex polyhedron.
+ */
+ public static roundConvexHull(
+ points: Float32Array,
+ borderRadius: number,
+ ): ColliderDesc | null {
+ const shape = new RoundConvexPolyhedron(points, null, borderRadius);
+ return new ColliderDesc(shape);
+ }
+
+ /**
+ * Creates a new collider descriptor that uses the given set of points assumed
+ * to form a round convex polyline (no convex-hull computation will be done).
+ *
+ * @param vertices - The vertices of the convex polyline.
+ * @param borderRadius - The radius of the round border added to the convex polyline.
+ */
+ public static roundConvexMesh(
+ vertices: Float32Array,
+ indices: Uint32Array | null,
+ borderRadius: number,
+ ): ColliderDesc | null {
+ const shape = new RoundConvexPolyhedron(
+ vertices,
+ indices,
+ borderRadius,
+ );
+ return new ColliderDesc(shape);
+ }
+
+ // #endif
+
+ /**
+ * Creates a new collider descriptor with a compound shape.
+ *
+ * @param shapes - The array of shapes composing this compound. Must not be empty, and
+ * must not contain other compound shapes (nested compound shapes are
+ * not allowed).
+ * @param positions - The array of positions for each shape (relative to the compound's origin).
+ * @param rotations - The array of rotations for each shape (relative to the compound's orientation).
+ */
+ public static compound(
+ shapes: Shape[],
+ positions: Vector[],
+ rotations: Rotation[],
+ ): ColliderDesc {
+ const shape = new Compound(shapes, positions, rotations);
+ return new ColliderDesc(shape);
+ }
+
+ /**
+ * Creates a new collider descriptor with a compound shape automatically created
+ * from a convex decomposition of the given triangle mesh (in 3D) or polyline (in 2D).
+ *
+ * @param vertices - The coordinates of the mesh's vertices.
+ * @param indices - The indices of the mesh's triangles (in 3D) or segments (in 2D).
+ * @param params - Optional VHACD parameters to control the decomposition.
+ * @returns The collider descriptor, or `null` if the decomposition did not produce
+ * any convex part (e.g. if the input mesh is degenerate).
+ */
+ public static convexDecomposition(
+ vertices: Float32Array,
+ indices: Uint32Array,
+ params?: VHACDParameters,
+ ): ColliderDesc | null {
+ let rawShape: RawShape;
+
+ if (params) {
+ // Convert TypeScript params to Rust params
+ const rawParams = new RawVHACDParameters();
+ if (params.alpha !== undefined) rawParams.alpha = params.alpha;
+ if (params.beta !== undefined) rawParams.beta = params.beta;
+ if (params.concavity !== undefined)
+ rawParams.concavity = params.concavity;
+ if (params.planeDownsampling !== undefined)
+ rawParams.plane_downsampling = params.planeDownsampling;
+ if (params.convexHullDownsampling !== undefined)
+ rawParams.convex_hull_downsampling =
+ params.convexHullDownsampling;
+ if (params.maxConvexHulls !== undefined)
+ rawParams.max_convex_hulls = params.maxConvexHulls;
+ if (params.resolution !== undefined)
+ rawParams.resolution = params.resolution;
+ if (params.convexHullApproximation !== undefined)
+ rawParams.convex_hull_approximation =
+ params.convexHullApproximation;
+
+ rawShape = RawShape.convexDecompositionWithParams(
+ vertices,
+ indices,
+ rawParams,
+ );
+ rawParams.free();
+ } else {
+ rawShape = RawShape.convexDecomposition(vertices, indices);
+ }
+
+ if (!rawShape) {
+ return null;
+ }
+
+ const shape = Shape.fromRawShape(rawShape);
+ return new ColliderDesc(shape);
+ }
+
+ // #if DIM2
+ /**
+ * Sets the position of the collider to be created relative to the rigid-body it is attached to.
+ */
+ public setTranslation(x: number, y: number): ColliderDesc {
+ if (typeof x != "number" || typeof y != "number")
+ throw TypeError("The translation components must be numbers.");
+
+ this.translation = {x: x, y: y};
+ return this;
+ }
+
+ // #endif
+
+ // #if DIM3
+ /**
+ * Sets the position of the collider to be created relative to the rigid-body it is attached to.
+ */
+ public setTranslation(x: number, y: number, z: number): ColliderDesc {
+ if (
+ typeof x != "number" ||
+ typeof y != "number" ||
+ typeof z != "number"
+ )
+ throw TypeError("The translation components must be numbers.");
+
+ this.translation = {x: x, y: y, z: z};
+ return this;
+ }
+
+ // #endif
+
+ /**
+ * Sets the rotation of the collider to be created relative to the rigid-body it is attached to.
+ *
+ * @param rot - The rotation of the collider to be created relative to the rigid-body it is attached to.
+ */
+ public setRotation(rot: Rotation): ColliderDesc {
+ // #if DIM2
+ this.rotation = rot;
+ // #endif
+ // #if DIM3
+ RotationOps.copy(this.rotation, rot);
+ // #endif
+ return this;
+ }
+
+ /**
+ * Sets whether or not the collider being created is a sensor.
+ *
+ * A sensor collider does not take part of the physics simulation, but generates
+ * proximity events.
+ *
+ * @param sensor - Set to `true` of the collider built is to be a sensor.
+ */
+ public setSensor(sensor: boolean): ColliderDesc {
+ this.isSensor = sensor;
+ return this;
+ }
+
+ /**
+ * Sets whether the created collider will be enabled or disabled.
+ * @param enabled − If set to `false` the collider will be disabled at creation.
+ */
+ public setEnabled(enabled: boolean): ColliderDesc {
+ this.enabled = enabled;
+ return this;
+ }
+
+ /**
+ * Sets the contact skin of the collider.
+ *
+ * The contact skin acts as if the collider was enlarged with a skin of width `skin_thickness`
+ * around it, keeping objects further apart when colliding.
+ *
+ * A non-zero contact skin can increase performance, and in some cases, stability. However
+ * it creates a small gap between colliding object (equal to the sum of their skin). If the
+ * skin is sufficiently small, this might not be visually significant or can be hidden by the
+ * rendering assets.
+ */
+ public setContactSkin(thickness: number): ColliderDesc {
+ this.contactSkin = thickness;
+ return this;
+ }
+
+ /**
+ * Sets the density of the collider being built.
+ *
+ * The mass and angular inertia tensor will be computed automatically based on this density and the collider’s shape.
+ *
+ * @param density - The density to set, must be greater or equal to 0. A density of 0 means that this collider
+ * will not affect the mass or angular inertia of the rigid-body it is attached to.
+ */
+ public setDensity(density: number): ColliderDesc {
+ this.massPropsMode = MassPropsMode.Density;
+ this.density = density;
+ return this;
+ }
+
+ /**
+ * Sets the mass of the collider being built.
+ *
+ * The angular inertia tensor will be computed automatically based on this mass and the collider’s shape.
+ *
+ * @param mass - The mass to set, must be greater or equal to 0.
+ */
+ public setMass(mass: number): ColliderDesc {
+ this.massPropsMode = MassPropsMode.Mass;
+ this.mass = mass;
+ return this;
+ }
+
+ // #if DIM2
+ /**
+ * Sets the mass properties of the collider being built.
+ *
+ * This replaces the mass-properties automatically computed from the collider's density and shape.
+ * These mass-properties will be added to the mass-properties of the rigid-body this collider will be attached to.
+ *
+ * @param mass − The mass of the collider to create.
+ * @param centerOfMass − The center-of-mass of the collider to create.
+ * @param principalAngularInertia − The principal angular inertia of the collider to create.
+ */
+ public setMassProperties(
+ mass: number,
+ centerOfMass: Vector,
+ principalAngularInertia: number,
+ ): ColliderDesc {
+ this.massPropsMode = MassPropsMode.MassProps;
+ this.mass = mass;
+ VectorOps.copy(this.centerOfMass, centerOfMass);
+ this.principalAngularInertia = principalAngularInertia;
+ return this;
+ }
+
+ // #endif
+
+ // #if DIM3
+ /**
+ * Sets the mass properties of the collider being built.
+ *
+ * This replaces the mass-properties automatically computed from the collider's density and shape.
+ * These mass-properties will be added to the mass-properties of the rigid-body this collider will be attached to.
+ *
+ * @param mass − The mass of the collider to create.
+ * @param centerOfMass − The center-of-mass of the collider to create.
+ * @param principalAngularInertia − The initial principal angular inertia of the collider to create.
+ * These are the eigenvalues of the angular inertia matrix.
+ * @param angularInertiaLocalFrame − The initial local angular inertia frame of the collider to create.
+ * These are the eigenvectors of the angular inertia matrix.
+ */
+ public setMassProperties(
+ mass: number,
+ centerOfMass: Vector,
+ principalAngularInertia: Vector,
+ angularInertiaLocalFrame: Rotation,
+ ): ColliderDesc {
+ this.massPropsMode = MassPropsMode.MassProps;
+ this.mass = mass;
+ VectorOps.copy(this.centerOfMass, centerOfMass);
+ VectorOps.copy(this.principalAngularInertia, principalAngularInertia);
+ RotationOps.copy(
+ this.angularInertiaLocalFrame,
+ angularInertiaLocalFrame,
+ );
+ return this;
+ }
+
+ // #endif
+
+ /**
+ * Sets the restitution coefficient of the collider to be created.
+ *
+ * @param restitution - The restitution coefficient in `[0, 1]`. A value of 0 (the default) means no bouncing behavior
+ * while 1 means perfect bouncing (though energy may still be lost due to numerical errors of the
+ * constraints solver).
+ */
+ public setRestitution(restitution: number): ColliderDesc {
+ this.restitution = restitution;
+ return this;
+ }
+
+ /**
+ * Sets the friction coefficient of the collider to be created.
+ *
+ * @param friction - The friction coefficient. Must be greater or equal to 0. This is generally smaller than 1. The
+ * higher the coefficient, the stronger friction forces will be for contacts with the collider
+ * being built.
+ */
+ public setFriction(friction: number): ColliderDesc {
+ this.friction = friction;
+ return this;
+ }
+
+ /**
+ * Sets the rule used to combine the friction coefficients of two colliders
+ * colliders involved in a contact.
+ *
+ * @param rule − The combine rule to apply.
+ */
+ public setFrictionCombineRule(rule: CoefficientCombineRule): ColliderDesc {
+ this.frictionCombineRule = rule;
+ return this;
+ }
+
+ /**
+ * Sets the rule used to combine the restitution coefficients of two colliders
+ * colliders involved in a contact.
+ *
+ * @param rule − The combine rule to apply.
+ */
+ public setRestitutionCombineRule(
+ rule: CoefficientCombineRule,
+ ): ColliderDesc {
+ this.restitutionCombineRule = rule;
+ return this;
+ }
+
+ /**
+ * Sets the collision groups used by this collider.
+ *
+ * Two colliders will interact iff. their collision groups are compatible.
+ * See the documentation of `InteractionGroups` for details on the used bit pattern.
+ *
+ * @param groups - The collision groups used for the collider being built.
+ */
+ public setCollisionGroups(groups: InteractionGroups): ColliderDesc {
+ this.collisionGroups = groups;
+ return this;
+ }
+
+ /**
+ * Sets the solver groups used by this collider.
+ *
+ * Forces between two colliders in contact will be computed iff their solver
+ * groups are compatible.
+ * See the documentation of `InteractionGroups` for details on the used bit pattern.
+ *
+ * @param groups - The solver groups used for the collider being built.
+ */
+ public setSolverGroups(groups: InteractionGroups): ColliderDesc {
+ this.solverGroups = groups;
+ return this;
+ }
+
+ /**
+ * Set the physics hooks active for this collider.
+ *
+ * Use this to enable custom filtering rules for contact/intersecstion pairs involving this collider.
+ *
+ * @param activeHooks - The hooks active for contact/intersection pairs involving this collider.
+ */
+ public setActiveHooks(activeHooks: ActiveHooks): ColliderDesc {
+ this.activeHooks = activeHooks;
+ return this;
+ }
+
+ /**
+ * Set the events active for this collider.
+ *
+ * Use this to enable contact and/or intersection event reporting for this collider.
+ *
+ * @param activeEvents - The events active for contact/intersection pairs involving this collider.
+ */
+ public setActiveEvents(activeEvents: ActiveEvents): ColliderDesc {
+ this.activeEvents = activeEvents;
+ return this;
+ }
+
+ /**
+ * Set the collision types active for this collider.
+ *
+ * @param activeCollisionTypes - The hooks active for contact/intersection pairs involving this collider.
+ */
+ public setActiveCollisionTypes(
+ activeCollisionTypes: ActiveCollisionTypes,
+ ): ColliderDesc {
+ this.activeCollisionTypes = activeCollisionTypes;
+ return this;
+ }
+
+ /**
+ * Sets the total force magnitude beyond which a contact force event can be emitted.
+ *
+ * @param threshold - The force threshold to set.
+ */
+ public setContactForceEventThreshold(threshold: number): ColliderDesc {
+ this.contactForceEventThreshold = threshold;
+ return this;
+ }
+}
diff --git a/typescript/src.ts/geometry/collider_set.ts b/typescript/src.ts/geometry/collider_set.ts
new file mode 100644
index 000000000..832b837a2
--- /dev/null
+++ b/typescript/src.ts/geometry/collider_set.ts
@@ -0,0 +1,213 @@
+import {RawColliderSet} from "../raw";
+import {Coarena} from "../coarena";
+import {RotationOps, VectorOps} from "../math";
+import {Collider, ColliderDesc, ColliderHandle} from "./collider";
+import {ImpulseJointHandle, IslandManager, RigidBodyHandle} from "../dynamics";
+import {RigidBodySet} from "../dynamics";
+
+/**
+ * A set of rigid bodies that can be handled by a physics pipeline.
+ *
+ * To avoid leaking WASM resources, this MUST be freed manually with `colliderSet.free()`
+ * once you are done using it (and all the rigid-bodies it created).
+ */
+export class ColliderSet {
+ raw: RawColliderSet;
+ private map: Coarena;
+
+ /**
+ * Release the WASM memory occupied by this collider set.
+ */
+ public free() {
+ if (!!this.raw) {
+ this.raw.free();
+ }
+ this.raw = undefined;
+
+ if (!!this.map) {
+ this.map.clear();
+ }
+ this.map = undefined;
+ }
+
+ constructor(raw?: RawColliderSet) {
+ this.raw = raw || new RawColliderSet();
+ this.map = new Coarena();
+ // Initialize the map with the existing elements, if any.
+ if (raw) {
+ raw.forEachColliderHandle((handle: ColliderHandle) => {
+ this.map.set(handle, new Collider(this, handle, null));
+ });
+ }
+ }
+
+ /** @internal */
+ public castClosure(
+ f?: (collider: Collider) => Res,
+ ): (handle: ColliderHandle) => Res | undefined {
+ return (handle) => {
+ if (!!f) {
+ return f(this.get(handle));
+ } else {
+ return undefined;
+ }
+ };
+ }
+
+ /** @internal */
+ public finalizeDeserialization(bodies: RigidBodySet) {
+ this.map.forEach((collider) =>
+ collider.finalizeDeserialization(bodies),
+ );
+ }
+
+ /**
+ * Creates a new collider and return its integer handle.
+ *
+ * @param bodies - The set of bodies where the collider's parent can be found.
+ * @param desc - The collider's description.
+ * @param parentHandle - The integer handle of the rigid-body this collider is attached to.
+ */
+ public createCollider(
+ bodies: RigidBodySet,
+ desc: ColliderDesc,
+ parentHandle: RigidBodyHandle,
+ ): Collider {
+ let hasParent = parentHandle != undefined && parentHandle != null;
+
+ if (hasParent && isNaN(parentHandle))
+ throw Error(
+ "Cannot create a collider with a parent rigid-body handle that is not a number.",
+ );
+
+ let rawShape = desc.shape.intoRaw();
+ let rawTra = VectorOps.intoRaw(desc.translation);
+ let rawRot = RotationOps.intoRaw(desc.rotation);
+ let rawCom = VectorOps.intoRaw(desc.centerOfMass);
+
+ // #if DIM3
+ let rawPrincipalInertia = VectorOps.intoRaw(
+ desc.principalAngularInertia,
+ );
+ let rawInertiaFrame = RotationOps.intoRaw(
+ desc.angularInertiaLocalFrame,
+ );
+ // #endif
+
+ let handle = this.raw.createCollider(
+ desc.enabled,
+ rawShape,
+ rawTra,
+ rawRot,
+ desc.massPropsMode,
+ desc.mass,
+ rawCom,
+ // #if DIM2
+ desc.principalAngularInertia,
+ // #endif
+ // #if DIM3
+ rawPrincipalInertia,
+ rawInertiaFrame,
+ // #endif
+ desc.density,
+ desc.friction,
+ desc.restitution,
+ desc.frictionCombineRule,
+ desc.restitutionCombineRule,
+ desc.isSensor,
+ desc.collisionGroups,
+ desc.solverGroups,
+ desc.activeCollisionTypes,
+ desc.activeHooks,
+ desc.activeEvents,
+ desc.contactForceEventThreshold,
+ desc.contactSkin,
+ hasParent,
+ hasParent ? parentHandle : 0,
+ bodies.raw,
+ );
+
+ rawShape.free();
+ rawTra.free();
+ rawRot.free();
+ rawCom.free();
+
+ // #if DIM3
+ rawPrincipalInertia.free();
+ rawInertiaFrame.free();
+ // #endif
+
+ let parent = hasParent ? bodies.get(parentHandle) : null;
+ let collider = new Collider(this, handle, parent, desc.shape);
+ this.map.set(handle, collider);
+ return collider;
+ }
+
+ /**
+ * Remove a collider from this set.
+ *
+ * @param handle - The integer handle of the collider to remove.
+ * @param bodies - The set of rigid-body containing the rigid-body the collider is attached to.
+ * @param wakeUp - If `true`, the rigid-body the removed collider is attached to will be woken-up automatically.
+ */
+ public remove(
+ handle: ColliderHandle,
+ islands: IslandManager,
+ bodies: RigidBodySet,
+ wakeUp: boolean,
+ ) {
+ this.raw.remove(handle, islands.raw, bodies.raw, wakeUp);
+ this.unmap(handle);
+ }
+
+ /**
+ * Internal function, do not call directly.
+ * @param handle
+ */
+ public unmap(handle: ImpulseJointHandle) {
+ this.map.delete(handle);
+ }
+
+ /**
+ * Gets the rigid-body with the given handle.
+ *
+ * @param handle - The handle of the rigid-body to retrieve.
+ */
+ public get(handle: ColliderHandle): Collider | null {
+ return this.map.get(handle);
+ }
+
+ /**
+ * The number of colliders on this set.
+ */
+ public len(): number {
+ return this.map.len();
+ }
+
+ /**
+ * Does this set contain a collider with the given handle?
+ *
+ * @param handle - The collider handle to check.
+ */
+ public contains(handle: ColliderHandle): boolean {
+ return this.get(handle) != null;
+ }
+
+ /**
+ * Applies the given closure to each collider contained by this set.
+ *
+ * @param f - The closure to apply.
+ */
+ public forEach(f: (collider: Collider) => void) {
+ this.map.forEach(f);
+ }
+
+ /**
+ * Gets all colliders in the list.
+ *
+ * @returns collider list.
+ */
+ public getAll(): Collider[] {
+ return this.map.getAll();
+ }
+}
diff --git a/typescript/src.ts/geometry/contact.ts b/typescript/src.ts/geometry/contact.ts
new file mode 100644
index 000000000..dc76b5576
--- /dev/null
+++ b/typescript/src.ts/geometry/contact.ts
@@ -0,0 +1,101 @@
+import {Vector, VectorOps, scratchBuffer} from "../math";
+import {RawShapeContact} from "../raw";
+
+/**
+ * The contact info between two shapes.
+ */
+export class ShapeContact {
+ /**
+ * Distance between the two contact points.
+ * If this is negative, this contact represents a penetration.
+ */
+ distance: number;
+
+ /**
+ * Position of the contact on the first shape.
+ */
+ point1: Vector;
+
+ /**
+ * Position of the contact on the second shape.
+ */
+ point2: Vector;
+
+ /**
+ * Contact normal, pointing towards the exterior of the first shape.
+ */
+ normal1: Vector;
+
+ /**
+ * Contact normal, pointing towards the exterior of the second shape.
+ * If these contact data are expressed in world-space, this normal is equal to -normal1.
+ */
+ normal2: Vector;
+
+ constructor(
+ dist: number,
+ point1: Vector,
+ point2: Vector,
+ normal1: Vector,
+ normal2: Vector,
+ ) {
+ this.distance = dist;
+ this.point1 = point1;
+ this.point2 = point2;
+ this.normal1 = normal1;
+ this.normal2 = normal2;
+ }
+
+ /**
+ * @param raw - The raw contact returned by the WASM query. It is freed by this method.
+ * @param target - If provided, this object is populated and returned instead of
+ * allocating a new one.
+ */
+ public static fromBuffer(
+ raw: RawShapeContact,
+ target?: ShapeContact,
+ ): ShapeContact {
+ if (!raw) return null;
+
+ raw.getComponents(scratchBuffer);
+ raw.free();
+
+ target ??= new ShapeContact(
+ 0,
+ VectorOps.zeros(),
+ VectorOps.zeros(),
+ VectorOps.zeros(),
+ VectorOps.zeros(),
+ );
+
+ target.distance = scratchBuffer[0];
+
+ // #if DIM2
+ target.point1.x = scratchBuffer[1];
+ target.point1.y = scratchBuffer[2];
+ target.point2.x = scratchBuffer[3];
+ target.point2.y = scratchBuffer[4];
+ target.normal1.x = scratchBuffer[5];
+ target.normal1.y = scratchBuffer[6];
+ target.normal2.x = scratchBuffer[7];
+ target.normal2.y = scratchBuffer[8];
+ // #endif
+
+ // #if DIM3
+ target.point1.x = scratchBuffer[1];
+ target.point1.y = scratchBuffer[2];
+ target.point1.z = scratchBuffer[3];
+ target.point2.x = scratchBuffer[4];
+ target.point2.y = scratchBuffer[5];
+ target.point2.z = scratchBuffer[6];
+ target.normal1.x = scratchBuffer[7];
+ target.normal1.y = scratchBuffer[8];
+ target.normal1.z = scratchBuffer[9];
+ target.normal2.x = scratchBuffer[10];
+ target.normal2.y = scratchBuffer[11];
+ target.normal2.z = scratchBuffer[12];
+ // #endif
+
+ return target;
+ }
+}
diff --git a/typescript/src.ts/geometry/feature.ts b/typescript/src.ts/geometry/feature.ts
new file mode 100644
index 000000000..bec9560d3
--- /dev/null
+++ b/typescript/src.ts/geometry/feature.ts
@@ -0,0 +1,16 @@
+// #if DIM2
+export enum FeatureType {
+ Vertex,
+ Face,
+ Unknown,
+}
+// #endif
+
+// #if DIM3
+export enum FeatureType {
+ Vertex,
+ Edge,
+ Face,
+ Unknown,
+}
+// #endif
diff --git a/typescript/src.ts/geometry/index.ts b/typescript/src.ts/geometry/index.ts
new file mode 100644
index 000000000..1bd19e50b
--- /dev/null
+++ b/typescript/src.ts/geometry/index.ts
@@ -0,0 +1,11 @@
+export * from "./broad_phase";
+export * from "./narrow_phase";
+export * from "./shape";
+export * from "./collider";
+export * from "./collider_set";
+export * from "./feature";
+export * from "./ray";
+export * from "./point";
+export * from "./toi";
+export * from "./interaction_groups";
+export * from "./contact";
diff --git a/typescript/src.ts/geometry/interaction_groups.ts b/typescript/src.ts/geometry/interaction_groups.ts
new file mode 100644
index 000000000..4d73fd31c
--- /dev/null
+++ b/typescript/src.ts/geometry/interaction_groups.ts
@@ -0,0 +1,18 @@
+/**
+ * Pairwise filtering using bit masks.
+ *
+ * This filtering method is based on two 16-bit values:
+ * - The interaction groups (the 16 left-most bits of `self.0`).
+ * - The interaction mask (the 16 right-most bits of `self.0`).
+ *
+ * An interaction is allowed between two filters `a` and `b` two conditions
+ * are met simultaneously:
+ * - The interaction groups of `a` has at least one bit set to `1` in common with the interaction mask of `b`.
+ * - The interaction groups of `b` has at least one bit set to `1` in common with the interaction mask of `a`.
+ * In other words, interactions are allowed between two filter iff. the following condition is met:
+ *
+ * ```
+ * ((a >> 16) & b) != 0 && ((b >> 16) & a) != 0
+ * ```
+ */
+export type InteractionGroups = number;
diff --git a/typescript/src.ts/geometry/narrow_phase.ts b/typescript/src.ts/geometry/narrow_phase.ts
new file mode 100644
index 000000000..c5d4974cb
--- /dev/null
+++ b/typescript/src.ts/geometry/narrow_phase.ts
@@ -0,0 +1,256 @@
+import {RawNarrowPhase, RawContactManifold} from "../raw";
+import {ColliderHandle} from "./collider";
+import {Vector, VectorOps, scratchBuffer} from "../math";
+
+/**
+ * The narrow-phase used for precise collision-detection.
+ *
+ * To avoid leaking WASM resources, this MUST be freed manually with `narrowPhase.free()`
+ * once you are done using it.
+ */
+export class NarrowPhase {
+ raw: RawNarrowPhase;
+ tempManifold: TempContactManifold;
+
+ /**
+ * Release the WASM memory occupied by this narrow-phase.
+ */
+ public free() {
+ if (!!this.raw) {
+ this.raw.free();
+ }
+ this.raw = undefined;
+ }
+
+ constructor(raw?: RawNarrowPhase) {
+ this.raw = raw || new RawNarrowPhase();
+ this.tempManifold = new TempContactManifold(null);
+ }
+
+ /**
+ * Enumerates all the colliders potentially in contact with the given collider.
+ *
+ * @param collider1 - The second collider involved in the contact.
+ * @param f - Closure that will be called on each collider that is in contact with `collider1`.
+ */
+ public contactPairsWith(
+ collider1: ColliderHandle,
+ f: (collider2: ColliderHandle) => void,
+ ) {
+ this.raw.contact_pairs_with(collider1, f);
+ }
+
+ /**
+ * Enumerates all the colliders intersecting the given colliders, assuming one of them
+ * is a sensor.
+ */
+ public intersectionPairsWith(
+ collider1: ColliderHandle,
+ f: (collider2: ColliderHandle) => void,
+ ) {
+ this.raw.intersection_pairs_with(collider1, f);
+ }
+
+ /**
+ * Iterates through all the contact manifolds between the given pair of colliders.
+ *
+ * @param collider1 - The first collider involved in the contact.
+ * @param collider2 - The second collider involved in the contact.
+ * @param f - Closure that will be called on each contact manifold between the two colliders. If the second argument
+ * passed to this closure is `true`, then the contact manifold data is flipped, i.e., methods like `localNormal1`
+ * actually apply to the `collider2` and fields like `localNormal2` apply to the `collider1`.
+ */
+ public contactPair(
+ collider1: ColliderHandle,
+ collider2: ColliderHandle,
+ f: (manifold: TempContactManifold, flipped: boolean) => void,
+ ) {
+ const rawPair = this.raw.contact_pair(collider1, collider2);
+
+ if (!!rawPair) {
+ const flipped = rawPair.collider1() != collider1;
+
+ let i;
+ for (i = 0; i < rawPair.numContactManifolds(); ++i) {
+ this.tempManifold.raw = rawPair.contactManifold(i);
+ if (!!this.tempManifold.raw) {
+ f(this.tempManifold, flipped);
+ }
+
+ // SAFETY: The RawContactManifold stores a raw pointer that will be invalidated
+ // at the next timestep. So we must be sure to free the pair here
+ // to avoid unsoundness in the Rust code.
+ this.tempManifold.free();
+ }
+ rawPair.free();
+ }
+ }
+
+ /**
+ * Returns `true` if `collider1` and `collider2` intersect and at least one of them is a sensor.
+ * @param collider1 − The first collider involved in the intersection.
+ * @param collider2 − The second collider involved in the intersection.
+ */
+ public intersectionPair(
+ collider1: ColliderHandle,
+ collider2: ColliderHandle,
+ ): boolean {
+ return this.raw.intersection_pair(collider1, collider2);
+ }
+}
+
+export class TempContactManifold {
+ raw: RawContactManifold;
+
+ public free() {
+ if (!!this.raw) {
+ this.raw.free();
+ }
+ this.raw = undefined;
+ }
+
+ constructor(raw: RawContactManifold) {
+ this.raw = raw;
+ }
+
+ /**
+ * The contact normal of the manifold, expressed in world-space.
+ *
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public normal(target?: Vector): Vector {
+ this.raw.normal(scratchBuffer);
+ return VectorOps.fromBuffer(scratchBuffer, target);
+ }
+
+ /**
+ * The contact normal of the manifold, expressed in the local-space of the first shape.
+ *
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public localNormal1(target?: Vector): Vector {
+ this.raw.local_n1(scratchBuffer);
+ return VectorOps.fromBuffer(scratchBuffer, target);
+ }
+
+ /**
+ * The contact normal of the manifold, expressed in the local-space of the second shape.
+ *
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public localNormal2(target?: Vector): Vector {
+ this.raw.local_n2(scratchBuffer);
+ return VectorOps.fromBuffer(scratchBuffer, target);
+ }
+
+ public subshape1(): number {
+ return this.raw.subshape1();
+ }
+
+ public subshape2(): number {
+ return this.raw.subshape2();
+ }
+
+ public numContacts(): number {
+ return this.raw.num_contacts();
+ }
+
+ /**
+ * The local-space contact point on the first shape, for the `i`-th contact.
+ *
+ * @param {number} i - The index of the contact to read.
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public localContactPoint1(i: number, target?: Vector): Vector | null {
+ const exists = this.raw.contact_local_p1(i, scratchBuffer);
+ return exists ? VectorOps.fromBuffer(scratchBuffer, target) : null;
+ }
+
+ /**
+ * The local-space contact point on the second shape, for the `i`-th contact.
+ *
+ * @param {number} i - The index of the contact to read.
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public localContactPoint2(i: number, target?: Vector): Vector | null {
+ const exists = this.raw.contact_local_p2(i, scratchBuffer);
+ return exists ? VectorOps.fromBuffer(scratchBuffer, target) : null;
+ }
+
+ public contactDist(i: number): number {
+ return this.raw.contact_dist(i);
+ }
+
+ public contactFid1(i: number): number {
+ return this.raw.contact_fid1(i);
+ }
+
+ public contactFid2(i: number): number {
+ return this.raw.contact_fid2(i);
+ }
+
+ public contactImpulse(i: number): number {
+ return this.raw.contact_impulse(i);
+ }
+
+ // #if DIM2
+ public contactTangentImpulse(i: number): number {
+ return this.raw.contact_tangent_impulse(i);
+ }
+ // #endif
+
+ // #if DIM3
+ public contactTangentImpulseX(i: number): number {
+ return this.raw.contact_tangent_impulse_x(i);
+ }
+
+ public contactTangentImpulseY(i: number): number {
+ return this.raw.contact_tangent_impulse_y(i);
+ }
+ // #endif
+
+ public numSolverContacts(): number {
+ return this.raw.num_solver_contacts();
+ }
+
+ /**
+ * The world-space position of the `i`-th solver contact point.
+ *
+ * @param {number} i - The index of the solver contact to read.
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public solverContactPoint(i: number, target?: Vector): Vector | null {
+ const exists = this.raw.solver_contact_point(i, scratchBuffer);
+ return exists ? VectorOps.fromBuffer(scratchBuffer, target) : null;
+ }
+
+ public solverContactDist(i: number): number {
+ return this.raw.solver_contact_dist(i);
+ }
+
+ public solverContactFriction(i: number): number {
+ return this.raw.solver_contact_friction(i);
+ }
+
+ public solverContactRestitution(i: number): number {
+ return this.raw.solver_contact_restitution(i);
+ }
+
+ /**
+ * The tangent (surface) velocity of the `i`-th solver contact point.
+ *
+ * @param {number} i - The index of the solver contact to read.
+ * @param {Vector?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ */
+ public solverContactTangentVelocity(i: number, target?: Vector): Vector {
+ this.raw.solver_contact_tangent_velocity(i, scratchBuffer);
+ return VectorOps.fromBuffer(scratchBuffer, target);
+ }
+}
diff --git a/typescript/src.ts/geometry/point.ts b/typescript/src.ts/geometry/point.ts
new file mode 100644
index 000000000..ec1335c13
--- /dev/null
+++ b/typescript/src.ts/geometry/point.ts
@@ -0,0 +1,117 @@
+import {Collider, ColliderHandle} from "./collider";
+import {Vector, VectorOps, scratchBuffer} from "../math";
+import {
+ RawFeatureType,
+ RawPointColliderProjection,
+ RawPointProjection,
+} from "../raw";
+import {FeatureType} from "./feature";
+import {ColliderSet} from "./collider_set";
+
+/**
+ * The projection of a point on a collider.
+ */
+export class PointProjection {
+ /**
+ * The projection of the point on the collider.
+ */
+ point: Vector;
+ /**
+ * Is the point inside of the collider?
+ */
+ isInside: boolean;
+
+ constructor(point: Vector, isInside: boolean) {
+ this.point = point;
+ this.isInside = isInside;
+ }
+
+ /**
+ * @param raw - The raw projection returned by the WASM query. It is freed by this method.
+ * @param target - If provided, this object is populated and returned instead of
+ * allocating a new one.
+ */
+ public static fromBuffer(
+ raw: RawPointProjection,
+ target?: PointProjection,
+ ): PointProjection {
+ if (!raw) return null;
+
+ raw.point(scratchBuffer);
+
+ target ??= new PointProjection(VectorOps.zeros(), false);
+ target.point = VectorOps.fromBuffer(scratchBuffer, target.point);
+ target.isInside = raw.isInside();
+
+ raw.free();
+ return target;
+ }
+}
+
+/**
+ * The projection of a point on a collider (includes the collider handle).
+ */
+export class PointColliderProjection {
+ /**
+ * The collider hit by the ray.
+ */
+ collider: Collider;
+ /**
+ * The projection of the point on the collider.
+ */
+ point: Vector;
+ /**
+ * Is the point inside of the collider?
+ */
+ isInside: boolean;
+
+ /**
+ * The type of the geometric feature the point was projected on.
+ */
+ featureType = FeatureType.Unknown;
+
+ /**
+ * The id of the geometric feature the point was projected on.
+ */
+ featureId: number | undefined = undefined;
+
+ constructor(
+ collider: Collider,
+ point: Vector,
+ isInside: boolean,
+ featureType?: FeatureType,
+ featureId?: number,
+ ) {
+ this.collider = collider;
+ this.point = point;
+ this.isInside = isInside;
+ if (featureId !== undefined) this.featureId = featureId;
+ if (featureType !== undefined) this.featureType = featureType;
+ }
+
+ /**
+ * @param colliderSet - The set the projected-on collider belongs to.
+ * @param raw - The raw projection returned by the WASM query. It is freed by this method.
+ * @param target - If provided, this object is populated and returned instead of
+ * allocating a new one.
+ */
+ public static fromBuffer(
+ colliderSet: ColliderSet,
+ raw: RawPointColliderProjection,
+ target?: PointColliderProjection,
+ ): PointColliderProjection {
+ if (!raw) return null;
+
+ raw.point(scratchBuffer);
+
+ target ??= new PointColliderProjection(null, VectorOps.zeros(), false);
+ target.collider = colliderSet.get(raw.colliderHandle());
+ target.point = VectorOps.fromBuffer(scratchBuffer, target.point);
+ target.isInside = raw.isInside();
+ target.featureType = raw.featureType() as number as FeatureType;
+ target.featureId = raw.featureId();
+
+ raw.free();
+ return target;
+ }
+}
diff --git a/typescript/src.ts/geometry/ray.ts b/typescript/src.ts/geometry/ray.ts
new file mode 100644
index 000000000..cd0356099
--- /dev/null
+++ b/typescript/src.ts/geometry/ray.ts
@@ -0,0 +1,211 @@
+import {Vector, VectorOps, scratchBuffer} from "../math";
+import {
+ RawFeatureType,
+ RawRayColliderIntersection,
+ RawRayColliderHit,
+ RawRayIntersection,
+} from "../raw";
+import {Collider} from "./collider";
+import {FeatureType} from "./feature";
+import {ColliderSet} from "./collider_set";
+
+/**
+ * A ray. This is a directed half-line.
+ */
+export class Ray {
+ /**
+ * The starting point of the ray.
+ */
+ public origin: Vector;
+ /**
+ * The direction of propagation of the ray.
+ */
+ public dir: Vector;
+
+ /**
+ * Builds a ray from its origin and direction.
+ *
+ * @param origin - The ray's starting point.
+ * @param dir - The ray's direction of propagation.
+ */
+ constructor(origin: Vector, dir: Vector) {
+ this.origin = origin;
+ this.dir = dir;
+ }
+
+ public pointAt(t: number): Vector {
+ return {
+ x: this.origin.x + this.dir.x * t,
+ y: this.origin.y + this.dir.y * t,
+ // #if DIM3
+ z: this.origin.z + this.dir.z * t,
+ // #endif
+ };
+ }
+}
+
+/**
+ * The intersection between a ray and a collider.
+ */
+export class RayIntersection {
+ /**
+ * The time-of-impact of the ray with the collider.
+ *
+ * The hit point is obtained from the ray's origin and direction: `origin + dir * timeOfImpact`.
+ */
+ timeOfImpact: number;
+ /**
+ * The normal of the collider at the hit point.
+ */
+ normal: Vector;
+
+ /**
+ * The type of the geometric feature the point was projected on.
+ */
+ featureType = FeatureType.Unknown;
+
+ /**
+ * The id of the geometric feature the point was projected on.
+ */
+ featureId: number | undefined = undefined;
+
+ constructor(
+ timeOfImpact: number,
+ normal: Vector,
+ featureType?: FeatureType,
+ featureId?: number,
+ ) {
+ this.timeOfImpact = timeOfImpact;
+ this.normal = normal;
+ if (featureId !== undefined) this.featureId = featureId;
+ if (featureType !== undefined) this.featureType = featureType;
+ }
+
+ /**
+ * @param raw - The raw intersection returned by the WASM query. It is freed by this method.
+ * @param target - If provided, this object is populated and returned instead of
+ * allocating a new one.
+ */
+ public static fromBuffer(
+ raw: RawRayIntersection,
+ target?: RayIntersection,
+ ): RayIntersection {
+ if (!raw) return null;
+
+ raw.normal(scratchBuffer);
+
+ target ??= new RayIntersection(0, VectorOps.zeros());
+ target.timeOfImpact = raw.time_of_impact();
+ target.normal = VectorOps.fromBuffer(scratchBuffer, target.normal);
+ target.featureType = raw.featureType() as number as FeatureType;
+ target.featureId = raw.featureId();
+
+ raw.free();
+ return target;
+ }
+}
+
+/**
+ * The intersection between a ray and a collider (includes the collider handle).
+ */
+export class RayColliderIntersection {
+ /**
+ * The collider hit by the ray.
+ */
+ collider: Collider;
+ /**
+ * The time-of-impact of the ray with the collider.
+ *
+ * The hit point is obtained from the ray's origin and direction: `origin + dir * timeOfImpact`.
+ */
+ timeOfImpact: number;
+ /**
+ * The normal of the collider at the hit point.
+ */
+ normal: Vector;
+
+ /**
+ * The type of the geometric feature the point was projected on.
+ */
+ featureType = FeatureType.Unknown;
+
+ /**
+ * The id of the geometric feature the point was projected on.
+ */
+ featureId: number | undefined = undefined;
+
+ constructor(
+ collider: Collider,
+ timeOfImpact: number,
+ normal: Vector,
+ featureType?: FeatureType,
+ featureId?: number,
+ ) {
+ this.collider = collider;
+ this.timeOfImpact = timeOfImpact;
+ this.normal = normal;
+ if (featureId !== undefined) this.featureId = featureId;
+ if (featureType !== undefined) this.featureType = featureType;
+ }
+
+ /**
+ * @param colliderSet - The set the hit collider belongs to.
+ * @param raw - The raw intersection returned by the WASM query. It is freed by this method.
+ * @param target - If provided, this object is populated and returned instead of
+ * allocating a new one.
+ */
+ public static fromBuffer(
+ colliderSet: ColliderSet,
+ raw: RawRayColliderIntersection,
+ target?: RayColliderIntersection,
+ ): RayColliderIntersection {
+ if (!raw) return null;
+
+ raw.normal(scratchBuffer);
+
+ target ??= new RayColliderIntersection(null, 0, VectorOps.zeros());
+ target.collider = colliderSet.get(raw.colliderHandle());
+ target.timeOfImpact = raw.time_of_impact();
+ target.normal = VectorOps.fromBuffer(scratchBuffer, target.normal);
+ target.featureType = raw.featureType() as number as FeatureType;
+ target.featureId = raw.featureId();
+
+ raw.free();
+ return target;
+ }
+}
+
+/**
+ * The time of impact between a ray and a collider.
+ */
+export class RayColliderHit {
+ /**
+ * The handle of the collider hit by the ray.
+ */
+ collider: Collider;
+ /**
+ * The time-of-impact of the ray with the collider.
+ *
+ * The hit point is obtained from the ray's origin and direction: `origin + dir * timeOfImpact`.
+ */
+ timeOfImpact: number;
+
+ constructor(collider: Collider, timeOfImpact: number) {
+ this.collider = collider;
+ this.timeOfImpact = timeOfImpact;
+ }
+
+ public static fromRaw(
+ colliderSet: ColliderSet,
+ raw: RawRayColliderHit,
+ ): RayColliderHit {
+ if (!raw) return null;
+
+ const result = new RayColliderHit(
+ colliderSet.get(raw.colliderHandle()),
+ raw.timeOfImpact(),
+ );
+ raw.free();
+ return result;
+ }
+}
diff --git a/typescript/src.ts/geometry/shape.ts b/typescript/src.ts/geometry/shape.ts
new file mode 100644
index 000000000..e74c8e54d
--- /dev/null
+++ b/typescript/src.ts/geometry/shape.ts
@@ -0,0 +1,1932 @@
+import {Vector, VectorOps, Rotation, RotationOps, scratchBuffer} from "../math";
+import {RawColliderSet, RawShape, RawShapeType} from "../raw";
+import {ShapeContact} from "./contact";
+import {PointProjection} from "./point";
+import {Ray, RayIntersection} from "./ray";
+import {ShapeCastHit} from "./toi";
+import {ColliderHandle} from "./collider";
+
+export abstract class Shape {
+ public abstract intoRaw(): RawShape;
+
+ /**
+ * The concrete type of this shape.
+ */
+ public abstract get type(): ShapeType;
+
+ /**
+ * instant mode without cache
+ */
+ public static fromRaw(
+ rawSet: RawColliderSet,
+ handle: ColliderHandle,
+ ): Shape {
+ const rawType = rawSet.coShapeType(handle);
+
+ if (rawType === RawShapeType.Compound) {
+ return Compound.fromRawShape(rawSet.coShape(handle));
+ }
+
+ let borderRadius: number;
+ let vs: Float32Array;
+ let indices: Uint32Array;
+ let halfHeight: number;
+ let radius: number;
+ let normal: Vector;
+
+ switch (rawType) {
+ case RawShapeType.Ball:
+ return new Ball(rawSet.coRadius(handle));
+ case RawShapeType.Cuboid:
+ rawSet.coHalfExtents(handle, scratchBuffer);
+
+ // #if DIM2
+ return new Cuboid(scratchBuffer[0], scratchBuffer[1]);
+ // #endif
+
+ // #if DIM3
+ return new Cuboid(
+ scratchBuffer[0],
+ scratchBuffer[1],
+ scratchBuffer[2],
+ );
+ // #endif
+
+ case RawShapeType.RoundCuboid:
+ borderRadius = rawSet.coRoundRadius(handle);
+ rawSet.coHalfExtents(handle, scratchBuffer);
+
+ // #if DIM2
+ return new RoundCuboid(
+ scratchBuffer[0],
+ scratchBuffer[1],
+ borderRadius,
+ );
+ // #endif
+
+ // #if DIM3
+ return new RoundCuboid(
+ scratchBuffer[0],
+ scratchBuffer[1],
+ scratchBuffer[2],
+ borderRadius,
+ );
+ // #endif
+
+ case RawShapeType.Capsule:
+ halfHeight = rawSet.coHalfHeight(handle);
+ radius = rawSet.coRadius(handle);
+ return new Capsule(halfHeight, radius);
+ case RawShapeType.Segment:
+ vs = rawSet.coVertices(handle);
+
+ // #if DIM2
+ return new Segment(
+ VectorOps.new(vs[0], vs[1]),
+ VectorOps.new(vs[2], vs[3]),
+ );
+ // #endif
+
+ // #if DIM3
+ return new Segment(
+ VectorOps.new(vs[0], vs[1], vs[2]),
+ VectorOps.new(vs[3], vs[4], vs[5]),
+ );
+ // #endif
+
+ case RawShapeType.Polyline:
+ vs = rawSet.coVertices(handle);
+ indices = rawSet.coIndices(handle);
+ return new Polyline(vs, indices);
+ case RawShapeType.Triangle:
+ vs = rawSet.coVertices(handle);
+
+ // #if DIM2
+ return new Triangle(
+ VectorOps.new(vs[0], vs[1]),
+ VectorOps.new(vs[2], vs[3]),
+ VectorOps.new(vs[4], vs[5]),
+ );
+ // #endif
+
+ // #if DIM3
+ return new Triangle(
+ VectorOps.new(vs[0], vs[1], vs[2]),
+ VectorOps.new(vs[3], vs[4], vs[5]),
+ VectorOps.new(vs[6], vs[7], vs[8]),
+ );
+ // #endif
+
+ case RawShapeType.RoundTriangle:
+ vs = rawSet.coVertices(handle);
+ borderRadius = rawSet.coRoundRadius(handle);
+
+ // #if DIM2
+ return new RoundTriangle(
+ VectorOps.new(vs[0], vs[1]),
+ VectorOps.new(vs[2], vs[3]),
+ VectorOps.new(vs[4], vs[5]),
+ borderRadius,
+ );
+ // #endif
+
+ // #if DIM3
+ return new RoundTriangle(
+ VectorOps.new(vs[0], vs[1], vs[2]),
+ VectorOps.new(vs[3], vs[4], vs[5]),
+ VectorOps.new(vs[6], vs[7], vs[8]),
+ borderRadius,
+ );
+ // #endif
+
+ case RawShapeType.HalfSpace:
+ rawSet.coHalfspaceNormal(handle, scratchBuffer);
+ normal = VectorOps.fromBuffer(scratchBuffer);
+ return new HalfSpace(normal);
+
+ case RawShapeType.Voxels:
+ const vox_data = rawSet.coVoxelData(handle);
+ const vox_size = rawSet.coVoxelSize(handle);
+ return new Voxels(vox_data, vox_size);
+
+ case RawShapeType.TriMesh:
+ vs = rawSet.coVertices(handle);
+ indices = rawSet.coIndices(handle);
+ const tri_flags = rawSet.coTriMeshFlags(handle);
+ return new TriMesh(vs, indices, tri_flags);
+
+ case RawShapeType.HeightField:
+ const heights = rawSet.coHeightfieldHeights(handle);
+ rawSet.coHeightfieldScale(handle, scratchBuffer);
+
+ // #if DIM2
+ const scale = {
+ x: scratchBuffer[0],
+ y: scratchBuffer[1],
+ };
+ return new Heightfield(heights, scale);
+ // #endif
+
+ // #if DIM3
+ const scale = {
+ x: scratchBuffer[0],
+ y: scratchBuffer[1],
+ z: scratchBuffer[2],
+ };
+ const nrows = rawSet.coHeightfieldNRows(handle);
+ const ncols = rawSet.coHeightfieldNCols(handle);
+ const hf_flags = rawSet.coHeightFieldFlags(handle);
+ return new Heightfield(nrows, ncols, heights, scale, hf_flags);
+ // #endif
+
+ // #if DIM2
+ case RawShapeType.ConvexPolygon:
+ vs = rawSet.coVertices(handle);
+ return new ConvexPolygon(vs, false);
+ case RawShapeType.RoundConvexPolygon:
+ vs = rawSet.coVertices(handle);
+ borderRadius = rawSet.coRoundRadius(handle);
+ return new RoundConvexPolygon(vs, borderRadius, false);
+ // #endif
+
+ // #if DIM3
+ case RawShapeType.ConvexPolyhedron:
+ vs = rawSet.coVertices(handle);
+ indices = rawSet.coIndices(handle);
+ return new ConvexPolyhedron(vs, indices);
+ case RawShapeType.RoundConvexPolyhedron:
+ vs = rawSet.coVertices(handle);
+ indices = rawSet.coIndices(handle);
+ borderRadius = rawSet.coRoundRadius(handle);
+ return new RoundConvexPolyhedron(vs, indices, borderRadius);
+ case RawShapeType.Cylinder:
+ halfHeight = rawSet.coHalfHeight(handle);
+ radius = rawSet.coRadius(handle);
+ return new Cylinder(halfHeight, radius);
+ case RawShapeType.RoundCylinder:
+ halfHeight = rawSet.coHalfHeight(handle);
+ radius = rawSet.coRadius(handle);
+ borderRadius = rawSet.coRoundRadius(handle);
+ return new RoundCylinder(halfHeight, radius, borderRadius);
+ case RawShapeType.Cone:
+ halfHeight = rawSet.coHalfHeight(handle);
+ radius = rawSet.coRadius(handle);
+ return new Cone(halfHeight, radius);
+ case RawShapeType.RoundCone:
+ halfHeight = rawSet.coHalfHeight(handle);
+ radius = rawSet.coRadius(handle);
+ borderRadius = rawSet.coRoundRadius(handle);
+ return new RoundCone(halfHeight, radius, borderRadius);
+ // #endif
+
+ default:
+ throw new Error("unknown shape type: " + rawType);
+ }
+ }
+
+ public static fromRawShape(rawShape: RawShape): Shape {
+ if (!rawShape) return null;
+
+ let extents: Vector;
+ let borderRadius: number;
+ let vs: Float32Array;
+ let indices: Uint32Array;
+ let halfHeight: number;
+ let radius: number;
+ let normal: Vector;
+ const rawType = rawShape.shapeType();
+
+ try {
+ switch (rawType) {
+ case RawShapeType.Ball:
+ return new Ball(rawShape.radius());
+ case RawShapeType.Cuboid:
+ extents = VectorOps.fromRaw(rawShape.halfExtents());
+ // #if DIM2
+ return new Cuboid(extents.x, extents.y);
+ // #endif
+
+ // #if DIM3
+ return new Cuboid(extents.x, extents.y, extents.z);
+ // #endif
+
+ case RawShapeType.RoundCuboid:
+ extents = VectorOps.fromRaw(rawShape.halfExtents());
+ borderRadius = rawShape.roundRadius();
+
+ // #if DIM2
+ return new RoundCuboid(extents.x, extents.y, borderRadius);
+ // #endif
+
+ // #if DIM3
+ return new RoundCuboid(
+ extents.x,
+ extents.y,
+ extents.z,
+ borderRadius,
+ );
+ // #endif
+
+ case RawShapeType.Capsule:
+ halfHeight = rawShape.halfHeight();
+ radius = rawShape.radius();
+ return new Capsule(halfHeight, radius);
+ case RawShapeType.Segment:
+ vs = rawShape.vertices();
+
+ // #if DIM2
+ return new Segment(
+ VectorOps.new(vs[0], vs[1]),
+ VectorOps.new(vs[2], vs[3]),
+ );
+ // #endif
+
+ // #if DIM3
+ return new Segment(
+ VectorOps.new(vs[0], vs[1], vs[2]),
+ VectorOps.new(vs[3], vs[4], vs[5]),
+ );
+ // #endif
+
+ case RawShapeType.Polyline:
+ vs = rawShape.vertices();
+ indices = rawShape.indices();
+ return new Polyline(vs, indices);
+ case RawShapeType.Triangle:
+ vs = rawShape.vertices();
+
+ // #if DIM2
+ return new Triangle(
+ VectorOps.new(vs[0], vs[1]),
+ VectorOps.new(vs[2], vs[3]),
+ VectorOps.new(vs[4], vs[5]),
+ );
+ // #endif
+
+ // #if DIM3
+ return new Triangle(
+ VectorOps.new(vs[0], vs[1], vs[2]),
+ VectorOps.new(vs[3], vs[4], vs[5]),
+ VectorOps.new(vs[6], vs[7], vs[8]),
+ );
+ // #endif
+
+ case RawShapeType.RoundTriangle:
+ vs = rawShape.vertices();
+ borderRadius = rawShape.roundRadius();
+
+ // #if DIM2
+ return new RoundTriangle(
+ VectorOps.new(vs[0], vs[1]),
+ VectorOps.new(vs[2], vs[3]),
+ VectorOps.new(vs[4], vs[5]),
+ borderRadius,
+ );
+ // #endif
+
+ // #if DIM3
+ return new RoundTriangle(
+ VectorOps.new(vs[0], vs[1], vs[2]),
+ VectorOps.new(vs[3], vs[4], vs[5]),
+ VectorOps.new(vs[6], vs[7], vs[8]),
+ borderRadius,
+ );
+ // #endif
+
+ case RawShapeType.HalfSpace:
+ normal = VectorOps.fromRaw(rawShape.halfspaceNormal());
+ return new HalfSpace(normal);
+
+ case RawShapeType.Voxels:
+ const vox_data = rawShape.voxelData();
+ const vox_size = VectorOps.fromRaw(rawShape.voxelSize());
+ return new Voxels(vox_data, vox_size);
+
+ case RawShapeType.TriMesh:
+ vs = rawShape.vertices();
+ indices = rawShape.indices();
+ const tri_flags = rawShape.triMeshFlags();
+ return new TriMesh(vs, indices, tri_flags);
+
+ case RawShapeType.HeightField:
+ const scale = VectorOps.fromRaw(
+ rawShape.heightfieldScale(),
+ );
+ const heights = rawShape.heightfieldHeights();
+
+ // #if DIM2
+ return new Heightfield(heights, scale);
+ // #endif
+
+ // #if DIM3
+ const nrows = rawShape.heightfieldNRows();
+ const ncols = rawShape.heightfieldNCols();
+ const hf_flags = rawShape.heightFieldFlags();
+ return new Heightfield(
+ nrows,
+ ncols,
+ heights,
+ scale,
+ hf_flags,
+ );
+ // #endif
+
+ // #if DIM2
+ case RawShapeType.ConvexPolygon:
+ vs = rawShape.vertices();
+ return new ConvexPolygon(vs, false);
+ case RawShapeType.RoundConvexPolygon:
+ vs = rawShape.vertices();
+ borderRadius = rawShape.roundRadius();
+ return new RoundConvexPolygon(vs, borderRadius, false);
+ // #endif
+
+ // #if DIM3
+ case RawShapeType.ConvexPolyhedron: {
+ const mesh = rawShape.convexMeshData();
+ if (!mesh) {
+ throw new Error(
+ "Failed to compute the convex hull of a convex polyhedron shape.",
+ );
+ }
+ vs = mesh.vertices;
+ indices = mesh.indices;
+ mesh.free();
+ return new ConvexPolyhedron(vs, indices);
+ }
+ case RawShapeType.RoundConvexPolyhedron: {
+ const mesh = rawShape.convexMeshData();
+ if (!mesh) {
+ throw new Error(
+ "Failed to compute the convex hull of a convex polyhedron shape.",
+ );
+ }
+ vs = mesh.vertices;
+ indices = mesh.indices;
+ mesh.free();
+ borderRadius = rawShape.roundRadius();
+ return new RoundConvexPolyhedron(vs, indices, borderRadius);
+ }
+ case RawShapeType.Cylinder:
+ halfHeight = rawShape.halfHeight();
+ radius = rawShape.radius();
+ return new Cylinder(halfHeight, radius);
+ case RawShapeType.RoundCylinder:
+ halfHeight = rawShape.halfHeight();
+ radius = rawShape.radius();
+ borderRadius = rawShape.roundRadius();
+ return new RoundCylinder(halfHeight, radius, borderRadius);
+ case RawShapeType.Cone:
+ halfHeight = rawShape.halfHeight();
+ radius = rawShape.radius();
+ return new Cone(halfHeight, radius);
+ case RawShapeType.RoundCone:
+ halfHeight = rawShape.halfHeight();
+ radius = rawShape.radius();
+ borderRadius = rawShape.roundRadius();
+ return new RoundCone(halfHeight, radius, borderRadius);
+ // #endif
+
+ case RawShapeType.Compound:
+ return Compound.fromRawShape(rawShape);
+ default:
+ throw new Error("unknown shape type: " + rawType);
+ }
+ } finally {
+ if (rawType !== RawShapeType.Compound) {
+ rawShape.free();
+ }
+ }
+ }
+
+ /**
+ * Computes the time of impact between two moving shapes.
+ * @param shapePos1 - The initial position of this shape.
+ * @param shapeRot1 - The rotation of this shape.
+ * @param shapeVel1 - The velocity of this shape.
+ * @param shape2 - The second moving shape.
+ * @param shapePos2 - The initial position of the second shape.
+ * @param shapeRot2 - The rotation of the second shape.
+ * @param shapeVel2 - The velocity of the second shape.
+ * @param targetDistance − If the shape moves closer to this distance from a collider, a hit
+ * will be returned.
+ * @param maxToi - The maximum time when the impact can happen.
+ * @param stopAtPenetration - If set to `false`, the linear shape-cast won’t immediately stop if
+ * the shape is penetrating another shape at its starting point **and** its trajectory is such
+ * that it’s on a path to exit that penetration state.
+ * @param {ShapeCastHit?} target - The object to be populated. If provided,
+ * the function returns this object instead of creating a new one.
+ * @returns If the two moving shapes collider at some point along their trajectories, this returns the
+ * time at which the two shape collider as well as the contact information during the impact. Returns
+ * `null` if the two shapes never collide along their paths.
+ */
+ public castShape(
+ shapePos1: Vector,
+ shapeRot1: Rotation,
+ shapeVel1: Vector,
+ shape2: Shape,
+ shapePos2: Vector,
+ shapeRot2: Rotation,
+ shapeVel2: Vector,
+ targetDistance: number,
+ maxToi: number,
+ stopAtPenetration: boolean,
+ target?: ShapeCastHit,
+ ): ShapeCastHit | null {
+ let rawPos1 = VectorOps.intoRaw(shapePos1);
+ let rawRot1 = RotationOps.intoRaw(shapeRot1);
+ let rawVel1 = VectorOps.intoRaw(shapeVel1);
+ let rawPos2 = VectorOps.intoRaw(shapePos2);
+ let rawRot2 = RotationOps.intoRaw(shapeRot2);
+ let rawVel2 = VectorOps.intoRaw(shapeVel2);
+
+ let rawShape1 = this.intoRaw();
+ let rawShape2 = shape2.intoRaw();
+
+ const rawShapeCastHit = rawShape1.castShape(
+ rawPos1,
+ rawRot1,
+ rawVel1,
+ rawShape2,
+ rawPos2,
+ rawRot2,
+ rawVel2,
+ targetDistance,
+ maxToi,
+ stopAtPenetration,
+ );
+
+ let result = null;
+ if (rawShapeCastHit) {
+ rawShapeCastHit.getComponents(scratchBuffer);
+ result = ShapeCastHit.fromBuffer(null, scratchBuffer, target);
+ rawShapeCastHit.free();
+ }
+
+ rawPos1.free();
+ rawRot1.free();
+ rawVel1.free();
+ rawPos2.free();
+ rawRot2.free();
+ rawVel2.free();
+
+ rawShape1.free();
+ rawShape2.free();
+
+ return result;
+ }
+
+ /**
+ * Tests if this shape intersects another shape.
+ *
+ * @param shapePos1 - The position of this shape.
+ * @param shapeRot1 - The rotation of this shape.
+ * @param shape2 - The second shape to test.
+ * @param shapePos2 - The position of the second shape.
+ * @param shapeRot2 - The rotation of the second shape.
+ * @returns `true` if the two shapes intersect, `false` if they don’t.
+ */
+ public intersectsShape(
+ shapePos1: Vector,
+ shapeRot1: Rotation,
+ shape2: Shape,
+ shapePos2: Vector,
+ shapeRot2: Rotation,
+ ): boolean {
+ let rawPos1 = VectorOps.intoRaw(shapePos1);
+ let rawRot1 = RotationOps.intoRaw(shapeRot1);
+ let rawPos2 = VectorOps.intoRaw(shapePos2);
+ let rawRot2 = RotationOps.intoRaw(shapeRot2);
+
+ let rawShape1 = this.intoRaw();
+ let rawShape2 = shape2.intoRaw();
+
+ let result = rawShape1.intersectsShape(
+ rawPos1,
+ rawRot1,
+ rawShape2,
+ rawPos2,
+ rawRot2,
+ );
+
+ rawPos1.free();
+ rawRot1.free();
+ rawPos2.free();
+ rawRot2.free();
+
+ rawShape1.free();
+ rawShape2.free();
+
+ return result;
+ }
+
+ /**
+ * Computes one pair of contact points between two shapes.
+ *
+ * @param shapePos1 - The initial position of this sahpe.
+ * @param shapeRot1 - The rotation of this shape.
+ * @param shape2 - The second shape.
+ * @param shapePos2 - The initial position of the second shape.
+ * @param shapeRot2 - The rotation of the second shape.
+ * @param prediction - The prediction value, if the shapes are separated by a distance greater than this value, test will fail.
+ * @returns `null` if the shapes are separated by a distance greater than prediction, otherwise contact details. The result is given in world-space.
+ */
+ contactShape(
+ shapePos1: Vector,
+ shapeRot1: Rotation,
+ shape2: Shape,
+ shapePos2: Vector,
+ shapeRot2: Rotation,
+ prediction: number,
+ target?: ShapeContact,
+ ): ShapeContact | null {
+ let rawPos1 = VectorOps.intoRaw(shapePos1);
+ let rawRot1 = RotationOps.intoRaw(shapeRot1);
+ let rawPos2 = VectorOps.intoRaw(shapePos2);
+ let rawRot2 = RotationOps.intoRaw(shapeRot2);
+
+ let rawShape1 = this.intoRaw();
+ let rawShape2 = shape2.intoRaw();
+
+ let result = ShapeContact.fromBuffer(
+ rawShape1.contactShape(
+ rawPos1,
+ rawRot1,
+ rawShape2,
+ rawPos2,
+ rawRot2,
+ prediction,
+ ),
+ target,
+ );
+
+ rawPos1.free();
+ rawRot1.free();
+ rawPos2.free();
+ rawRot2.free();
+
+ rawShape1.free();
+ rawShape2.free();
+
+ return result;
+ }
+
+ containsPoint(
+ shapePos: Vector,
+ shapeRot: Rotation,
+ point: Vector,
+ ): boolean {
+ let rawPos = VectorOps.intoRaw(shapePos);
+ let rawRot = RotationOps.intoRaw(shapeRot);
+ let rawPoint = VectorOps.intoRaw(point);
+ let rawShape = this.intoRaw();
+
+ let result = rawShape.containsPoint(rawPos, rawRot, rawPoint);
+
+ rawPos.free();
+ rawRot.free();
+ rawPoint.free();
+ rawShape.free();
+
+ return result;
+ }
+
+ projectPoint(
+ shapePos: Vector,
+ shapeRot: Rotation,
+ point: Vector,
+ solid: boolean,
+ target?: PointProjection,
+ ): PointProjection {
+ let rawPos = VectorOps.intoRaw(shapePos);
+ let rawRot = RotationOps.intoRaw(shapeRot);
+ let rawPoint = VectorOps.intoRaw(point);
+ let rawShape = this.intoRaw();
+
+ let result = PointProjection.fromBuffer(
+ rawShape.projectPoint(rawPos, rawRot, rawPoint, solid),
+ target,
+ );
+
+ rawPos.free();
+ rawRot.free();
+ rawPoint.free();
+ rawShape.free();
+
+ return result;
+ }
+
+ intersectsRay(
+ ray: Ray,
+ shapePos: Vector,
+ shapeRot: Rotation,
+ maxToi: number,
+ ): boolean {
+ let rawPos = VectorOps.intoRaw(shapePos);
+ let rawRot = RotationOps.intoRaw(shapeRot);
+ let rawRayOrig = VectorOps.intoRaw(ray.origin);
+ let rawRayDir = VectorOps.intoRaw(ray.dir);
+ let rawShape = this.intoRaw();
+
+ let result = rawShape.intersectsRay(
+ rawPos,
+ rawRot,
+ rawRayOrig,
+ rawRayDir,
+ maxToi,
+ );
+
+ rawPos.free();
+ rawRot.free();
+ rawRayOrig.free();
+ rawRayDir.free();
+ rawShape.free();
+
+ return result;
+ }
+
+ castRay(
+ ray: Ray,
+ shapePos: Vector,
+ shapeRot: Rotation,
+ maxToi: number,
+ solid: boolean,
+ ): number {
+ let rawPos = VectorOps.intoRaw(shapePos);
+ let rawRot = RotationOps.intoRaw(shapeRot);
+ let rawRayOrig = VectorOps.intoRaw(ray.origin);
+ let rawRayDir = VectorOps.intoRaw(ray.dir);
+ let rawShape = this.intoRaw();
+
+ let result = rawShape.castRay(
+ rawPos,
+ rawRot,
+ rawRayOrig,
+ rawRayDir,
+ maxToi,
+ solid,
+ );
+
+ rawPos.free();
+ rawRot.free();
+ rawRayOrig.free();
+ rawRayDir.free();
+ rawShape.free();
+
+ return result;
+ }
+
+ castRayAndGetNormal(
+ ray: Ray,
+ shapePos: Vector,
+ shapeRot: Rotation,
+ maxToi: number,
+ solid: boolean,
+ target?: RayIntersection,
+ ): RayIntersection {
+ let rawPos = VectorOps.intoRaw(shapePos);
+ let rawRot = RotationOps.intoRaw(shapeRot);
+ let rawRayOrig = VectorOps.intoRaw(ray.origin);
+ let rawRayDir = VectorOps.intoRaw(ray.dir);
+ let rawShape = this.intoRaw();
+
+ let result = RayIntersection.fromBuffer(
+ rawShape.castRayAndGetNormal(
+ rawPos,
+ rawRot,
+ rawRayOrig,
+ rawRayDir,
+ maxToi,
+ solid,
+ ),
+ target,
+ );
+
+ rawPos.free();
+ rawRot.free();
+ rawRayOrig.free();
+ rawRayDir.free();
+ rawShape.free();
+
+ return result;
+ }
+}
+
+// #if DIM2
+/**
+ * An enumeration representing the type of a shape.
+ */
+export enum ShapeType {
+ Ball = 0,
+ Cuboid = 1,
+ Capsule = 2,
+ Segment = 3,
+ Polyline = 4,
+ Triangle = 5,
+ TriMesh = 6,
+ HeightField = 7,
+ Compound = 8,
+ ConvexPolygon = 9,
+ RoundCuboid = 10,
+ RoundTriangle = 11,
+ RoundConvexPolygon = 12,
+ HalfSpace = 13,
+ Voxels = 14,
+}
+
+// #endif
+
+// #if DIM3
+
+/**
+ * An enumeration representing the type of a shape.
+ */
+export enum ShapeType {
+ Ball = 0,
+ Cuboid = 1,
+ Capsule = 2,
+ Segment = 3,
+ Polyline = 4,
+ Triangle = 5,
+ TriMesh = 6,
+ HeightField = 7,
+ Compound = 8,
+ ConvexPolyhedron = 9,
+ Cylinder = 10,
+ Cone = 11,
+ RoundCuboid = 12,
+ RoundTriangle = 13,
+ RoundCylinder = 14,
+ RoundCone = 15,
+ RoundConvexPolyhedron = 16,
+ HalfSpace = 17,
+ Voxels = 18,
+}
+
+// NOTE: this **must** match the bits in the HeightFieldFlags on the rust side.
+/**
+ * Flags controlling the behavior of some operations involving heightfields.
+ */
+export enum HeightFieldFlags {
+ /**
+ * If set, a special treatment will be applied to contact manifold calculation to eliminate
+ * or fix contacts normals that could lead to incorrect bumps in physics simulation (especially
+ * on flat surfaces).
+ *
+ * This is achieved by taking into account adjacent triangle normals when computing contact
+ * points for a given triangle.
+ */
+ FIX_INTERNAL_EDGES = 0b0000_0001,
+}
+
+// #endif
+
+// NOTE: this **must** match the TriMeshFlags on the rust side.
+/**
+ * Flags controlling the behavior of the triangle mesh creation and of some
+ * operations involving triangle meshes.
+ */
+export enum TriMeshFlags {
+ // NOTE: these two flags are not really useful in JS.
+ //
+ // /**
+ // * If set, the half-edge topology of the trimesh will be computed if possible.
+ // */
+ // HALF_EDGE_TOPOLOGY = 0b0000_0001,
+ // /** If set, the half-edge topology and connected components of the trimesh will be computed if possible.
+ // *
+ // * Because of the way it is currently implemented, connected components can only be computed on
+ // * a mesh where the half-edge topology computation succeeds. It will no longer be the case in the
+ // * future once we decouple the computations.
+ // */
+ // CONNECTED_COMPONENTS = 0b0000_0010,
+ /**
+ * If set, any triangle that results in a failing half-hedge topology computation will be deleted.
+ */
+ DELETE_BAD_TOPOLOGY_TRIANGLES = 0b0000_0100,
+ /**
+ * If set, the trimesh will be assumed to be oriented (with outward normals).
+ *
+ * The pseudo-normals of its vertices and edges will be computed.
+ */
+ ORIENTED = 0b0000_1000,
+ /**
+ * If set, the duplicate vertices of the trimesh will be merged.
+ *
+ * Two vertices with the exact same coordinates will share the same entry on the
+ * vertex buffer and the index buffer is adjusted accordingly.
+ */
+ MERGE_DUPLICATE_VERTICES = 0b0001_0000,
+ /**
+ * If set, the triangles sharing two vertices with identical index values will be removed.
+ *
+ * Because of the way it is currently implemented, this methods implies that duplicate
+ * vertices will be merged. It will no longer be the case in the future once we decouple
+ * the computations.
+ */
+ DELETE_DEGENERATE_TRIANGLES = 0b0010_0000,
+ /**
+ * If set, two triangles sharing three vertices with identical index values (in any order)
+ * will be removed.
+ *
+ * Because of the way it is currently implemented, this methods implies that duplicate
+ * vertices will be merged. It will no longer be the case in the future once we decouple
+ * the computations.
+ */
+ DELETE_DUPLICATE_TRIANGLES = 0b0100_0000,
+ /**
+ * If set, a special treatment will be applied to contact manifold calculation to eliminate
+ * or fix contacts normals that could lead to incorrect bumps in physics simulation
+ * (especially on flat surfaces).
+ *
+ * This is achieved by taking into account adjacent triangle normals when computing contact
+ * points for a given triangle.
+ *
+ * /!\ NOT SUPPORTED IN THE 2D VERSION OF RAPIER.
+ */
+ FIX_INTERNAL_EDGES = 0b1000_0000 | TriMeshFlags.MERGE_DUPLICATE_VERTICES,
+}
+
+/**
+ * A shape that is a sphere in 3D and a circle in 2D.
+ */
+export class Ball extends Shape {
+ readonly type = ShapeType.Ball;
+
+ /**
+ * The balls radius.
+ */
+ radius: number;
+
+ /**
+ * Creates a new ball with the given radius.
+ * @param radius - The balls radius.
+ */
+ constructor(radius: number) {
+ super();
+ this.radius = radius;
+ }
+
+ public intoRaw(): RawShape {
+ return RawShape.ball(this.radius);
+ }
+}
+
+export class HalfSpace extends Shape {
+ readonly type = ShapeType.HalfSpace;
+
+ /**
+ * The outward normal of the half-space.
+ */
+ normal: Vector;
+
+ /**
+ * Creates a new halfspace delimited by an infinite plane.
+ *
+ * @param normal - The outward normal of the plane.
+ */
+ constructor(normal: Vector) {
+ super();
+ this.normal = normal;
+ }
+
+ public intoRaw(): RawShape {
+ let n = VectorOps.intoRaw(this.normal);
+ let result = RawShape.halfspace(n);
+ n.free();
+ return result;
+ }
+}
+
+/**
+ * A shape that is a box in 3D and a rectangle in 2D.
+ */
+export class Cuboid extends Shape {
+ readonly type = ShapeType.Cuboid;
+
+ /**
+ * The half extent of the cuboid along each coordinate axis.
+ */
+ halfExtents: Vector;
+
+ // #if DIM2
+ /**
+ * Creates a new 2D rectangle.
+ * @param hx - The half width of the rectangle.
+ * @param hy - The helf height of the rectangle.
+ */
+ constructor(hx: number, hy: number) {
+ super();
+ this.halfExtents = VectorOps.new(hx, hy);
+ }
+
+ // #endif
+
+ // #if DIM3
+ /**
+ * Creates a new 3D cuboid.
+ * @param hx - The half width of the cuboid.
+ * @param hy - The half height of the cuboid.
+ * @param hz - The half depth of the cuboid.
+ */
+ constructor(hx: number, hy: number, hz: number) {
+ super();
+ this.halfExtents = VectorOps.new(hx, hy, hz);
+ }
+
+ // #endif
+
+ public intoRaw(): RawShape {
+ // #if DIM2
+ return RawShape.cuboid(this.halfExtents.x, this.halfExtents.y);
+ // #endif
+
+ // #if DIM3
+ return RawShape.cuboid(
+ this.halfExtents.x,
+ this.halfExtents.y,
+ this.halfExtents.z,
+ );
+ // #endif
+ }
+}
+
+/**
+ * A shape that is a box in 3D and a rectangle in 2D, with round corners.
+ */
+export class RoundCuboid extends Shape {
+ readonly type = ShapeType.RoundCuboid;
+
+ /**
+ * The half extent of the cuboid along each coordinate axis.
+ */
+ halfExtents: Vector;
+
+ /**
+ * The radius of the cuboid's round border.
+ */
+ borderRadius: number;
+
+ // #if DIM2
+ /**
+ * Creates a new 2D rectangle.
+ * @param hx - The half width of the rectangle.
+ * @param hy - The helf height of the rectangle.
+ * @param borderRadius - The radius of the borders of this cuboid. This will
+ * effectively increase the half-extents of the cuboid by this radius.
+ */
+ constructor(hx: number, hy: number, borderRadius: number) {
+ super();
+ this.halfExtents = VectorOps.new(hx, hy);
+ this.borderRadius = borderRadius;
+ }
+
+ // #endif
+
+ // #if DIM3
+ /**
+ * Creates a new 3D cuboid.
+ * @param hx - The half width of the cuboid.
+ * @param hy - The half height of the cuboid.
+ * @param hz - The half depth of the cuboid.
+ * @param borderRadius - The radius of the borders of this cuboid. This will
+ * effectively increase the half-extents of the cuboid by this radius.
+ */
+ constructor(hx: number, hy: number, hz: number, borderRadius: number) {
+ super();
+ this.halfExtents = VectorOps.new(hx, hy, hz);
+ this.borderRadius = borderRadius;
+ }
+
+ // #endif
+
+ public intoRaw(): RawShape {
+ // #if DIM2
+ return RawShape.roundCuboid(
+ this.halfExtents.x,
+ this.halfExtents.y,
+ this.borderRadius,
+ );
+ // #endif
+
+ // #if DIM3
+ return RawShape.roundCuboid(
+ this.halfExtents.x,
+ this.halfExtents.y,
+ this.halfExtents.z,
+ this.borderRadius,
+ );
+ // #endif
+ }
+}
+
+/**
+ * A shape that is a capsule.
+ */
+export class Capsule extends Shape {
+ readonly type = ShapeType.Capsule;
+
+ /**
+ * The radius of the capsule's basis.
+ */
+ radius: number;
+
+ /**
+ * The capsule's half height, along the `y` axis.
+ */
+ halfHeight: number;
+
+ /**
+ * Creates a new capsule with the given radius and half-height.
+ * @param halfHeight - The balls half-height along the `y` axis.
+ * @param radius - The balls radius.
+ */
+ constructor(halfHeight: number, radius: number) {
+ super();
+ this.halfHeight = halfHeight;
+ this.radius = radius;
+ }
+
+ public intoRaw(): RawShape {
+ return RawShape.capsule(this.halfHeight, this.radius);
+ }
+}
+
+/**
+ * A shape that is a segment.
+ */
+export class Segment extends Shape {
+ readonly type = ShapeType.Segment;
+
+ /**
+ * The first point of the segment.
+ */
+ a: Vector;
+
+ /**
+ * The second point of the segment.
+ */
+ b: Vector;
+
+ /**
+ * Creates a new segment shape.
+ * @param a - The first point of the segment.
+ * @param b - The second point of the segment.
+ */
+ constructor(a: Vector, b: Vector) {
+ super();
+ this.a = a;
+ this.b = b;
+ }
+
+ public intoRaw(): RawShape {
+ let ra = VectorOps.intoRaw(this.a);
+ let rb = VectorOps.intoRaw(this.b);
+ let result = RawShape.segment(ra, rb);
+ ra.free();
+ rb.free();
+ return result;
+ }
+}
+
+/**
+ * A shape that is a segment.
+ */
+export class Triangle extends Shape {
+ readonly type = ShapeType.Triangle;
+
+ /**
+ * The first point of the triangle.
+ */
+ a: Vector;
+
+ /**
+ * The second point of the triangle.
+ */
+ b: Vector;
+
+ /**
+ * The second point of the triangle.
+ */
+ c: Vector;
+
+ /**
+ * Creates a new triangle shape.
+ *
+ * @param a - The first point of the triangle.
+ * @param b - The second point of the triangle.
+ * @param c - The third point of the triangle.
+ */
+ constructor(a: Vector, b: Vector, c: Vector) {
+ super();
+ this.a = a;
+ this.b = b;
+ this.c = c;
+ }
+
+ public intoRaw(): RawShape {
+ let ra = VectorOps.intoRaw(this.a);
+ let rb = VectorOps.intoRaw(this.b);
+ let rc = VectorOps.intoRaw(this.c);
+ let result = RawShape.triangle(ra, rb, rc);
+ ra.free();
+ rb.free();
+ rc.free();
+ return result;
+ }
+}
+
+/**
+ * A shape that is a triangle with round borders and a non-zero thickness.
+ */
+export class RoundTriangle extends Shape {
+ readonly type = ShapeType.RoundTriangle;
+
+ /**
+ * The first point of the triangle.
+ */
+ a: Vector;
+
+ /**
+ * The second point of the triangle.
+ */
+ b: Vector;
+
+ /**
+ * The second point of the triangle.
+ */
+ c: Vector;
+
+ /**
+ * The radius of the triangles's rounded edges and vertices.
+ * In 3D, this is also equal to half the thickness of the round triangle.
+ */
+ borderRadius: number;
+
+ /**
+ * Creates a new triangle shape with round corners.
+ *
+ * @param a - The first point of the triangle.
+ * @param b - The second point of the triangle.
+ * @param c - The third point of the triangle.
+ * @param borderRadius - The radius of the borders of this triangle. In 3D,
+ * this is also equal to half the thickness of the triangle.
+ */
+ constructor(a: Vector, b: Vector, c: Vector, borderRadius: number) {
+ super();
+ this.a = a;
+ this.b = b;
+ this.c = c;
+ this.borderRadius = borderRadius;
+ }
+
+ public intoRaw(): RawShape {
+ let ra = VectorOps.intoRaw(this.a);
+ let rb = VectorOps.intoRaw(this.b);
+ let rc = VectorOps.intoRaw(this.c);
+ let result = RawShape.roundTriangle(ra, rb, rc, this.borderRadius);
+ ra.free();
+ rb.free();
+ rc.free();
+ return result;
+ }
+}
+
+/**
+ * A shape that is a triangle mesh.
+ */
+export class Polyline extends Shape {
+ readonly type = ShapeType.Polyline;
+
+ /**
+ * The vertices of the polyline.
+ */
+ vertices: Float32Array;
+
+ /**
+ * The indices of the segments.
+ */
+ indices: Uint32Array;
+
+ /**
+ * Creates a new polyline shape.
+ *
+ * @param vertices - The coordinates of the polyline's vertices.
+ * @param indices - The indices of the polyline's segments. If this is `null` or not provided, then
+ * the vertices are assumed to form a line strip.
+ */
+ constructor(vertices: Float32Array, indices?: Uint32Array) {
+ super();
+ this.vertices = vertices;
+ this.indices = indices ?? new Uint32Array(0);
+ }
+
+ public intoRaw(): RawShape {
+ return RawShape.polyline(this.vertices, this.indices);
+ }
+}
+
+/**
+ * A shape made of voxels.
+ */
+export class Voxels extends Shape {
+ readonly type = ShapeType.Voxels;
+
+ /**
+ * The points or grid coordinates used to initialize the voxels.
+ */
+ data: Float32Array | Int32Array;
+
+ /**
+ * The dimensions of each voxel.
+ */
+ voxelSize: Vector;
+
+ /**
+ * Creates a new shape made of voxels.
+ *
+ * @param data - Defines the set of voxels. If this is a `Int32Array` then
+ * each voxel is defined from its (signed) grid coordinates,
+ * with 3 (resp 2) contiguous integers per voxel in 3D (resp 2D).
+ * If this is a `Float32Array`, each voxel will be such that
+ * they contain at least one point from this array (where each
+ * point is defined from 3 (resp 2) contiguous numbers per point
+ * in 3D (resp 2D).
+ * @param voxelSize - The size of each voxel.
+ */
+ constructor(data: Float32Array | Int32Array, voxelSize: Vector) {
+ super();
+ this.data = data;
+ this.voxelSize = voxelSize;
+ }
+
+ public intoRaw(): RawShape {
+ let voxelSize = VectorOps.intoRaw(this.voxelSize);
+
+ let result;
+ if (this.data instanceof Int32Array) {
+ result = RawShape.voxels(voxelSize, this.data);
+ } else {
+ result = RawShape.voxelsFromPoints(voxelSize, this.data);
+ }
+
+ voxelSize.free();
+ return result;
+ }
+}
+
+/**
+ * A compound shape, consisting of multiple sub-shapes with relative positions.
+ */
+export class Compound extends Shape {
+ readonly type = ShapeType.Compound;
+
+ /**
+ * The shapes composing this compound shape.
+ */
+ shapes: Shape[];
+
+ /**
+ * The positions of each sub-shape relative to the compound's origin.
+ */
+ positions: Vector[];
+
+ /**
+ * The rotations of each sub-shape relative to the compound's orientation.
+ */
+ rotations: Rotation[];
+
+ /**
+ * Creates a new compound shape.
+ *
+ * @param shapes - The array of shapes composing this compound. Must not be empty,
+ * and must not contain other compound shapes (nested compound shapes
+ * are not allowed).
+ * @param positions - The array of positions for each shape.
+ * @param rotations - The array of rotations for each shape.
+ */
+ constructor(shapes: Shape[], positions: Vector[], rotations: Rotation[]) {
+ super();
+
+ if (
+ shapes.length !== positions.length ||
+ shapes.length !== rotations.length
+ ) {
+ throw new Error(
+ "shapes, positions, and rotations arrays must have the same length",
+ );
+ }
+
+ if (shapes.length === 0) {
+ throw new Error("a compound shape must contain at least one shape");
+ }
+
+ if (shapes.some((shape) => shape.type === ShapeType.Compound)) {
+ throw new Error("nested compound shapes are not allowed");
+ }
+
+ this.shapes = shapes;
+ this.positions = positions;
+ this.rotations = rotations;
+ }
+
+ /**
+ * Reconstructs a compound shape from its raw representation.
+ *
+ * This takes ownership of `rawShape` and always frees it before returning.
+ */
+ public static fromRawShape(rawShape: RawShape): Compound {
+ try {
+ const numShapes = rawShape.compoundLen();
+ if (numShapes == null) {
+ throw new Error("Expected a raw compound shape.");
+ }
+
+ const shapes = new Array(numShapes);
+ const positions = new Array(numShapes);
+ const rotations = new Array(numShapes);
+
+ for (let i = 0; i < numShapes; i++) {
+ shapes[i] = Shape.fromRawShape(rawShape.compoundShape(i));
+ positions[i] = VectorOps.fromRaw(
+ rawShape.compoundTranslation(i),
+ );
+ rotations[i] = RotationOps.fromRaw(
+ rawShape.compoundRotation(i),
+ );
+ }
+
+ return new Compound(shapes, positions, rotations);
+ } finally {
+ rawShape.free();
+ }
+ }
+
+ public intoRaw(): RawShape {
+ const rawShapes = this.shapes.map((s) => s.intoRaw());
+
+ // #if DIM2
+ const positions = new Float32Array(this.positions.length * 2);
+ this.positions.forEach((pos, i) => {
+ positions[i * 2] = pos.x;
+ positions[i * 2 + 1] = pos.y;
+ });
+
+ const rotations = new Float32Array(this.rotations.length);
+ this.rotations.forEach((rot, i) => {
+ rotations[i] = rot;
+ });
+ // #endif
+
+ // #if DIM3
+ const positions = new Float32Array(this.positions.length * 3);
+ this.positions.forEach((pos, i) => {
+ positions[i * 3] = pos.x;
+ positions[i * 3 + 1] = pos.y;
+ positions[i * 3 + 2] = pos.z;
+ });
+
+ const rotations = new Float32Array(this.rotations.length * 4);
+ this.rotations.forEach((rot, i) => {
+ rotations[i * 4] = rot.x;
+ rotations[i * 4 + 1] = rot.y;
+ rotations[i * 4 + 2] = rot.z;
+ rotations[i * 4 + 3] = rot.w;
+ });
+ // #endif
+
+ return RawShape.compound(rawShapes, positions, rotations);
+ }
+}
+
+/**
+ * A shape that is a triangle mesh.
+ */
+export class TriMesh extends Shape {
+ readonly type = ShapeType.TriMesh;
+
+ /**
+ * The vertices of the triangle mesh.
+ */
+ vertices: Float32Array;
+
+ /**
+ * The indices of the triangles.
+ */
+ indices: Uint32Array;
+
+ /**
+ * The triangle mesh flags.
+ */
+ flags: TriMeshFlags;
+
+ /**
+ * Creates a new triangle mesh shape.
+ *
+ * @param vertices - The coordinates of the triangle mesh's vertices.
+ * @param indices - The indices of the triangle mesh's triangles.
+ */
+ constructor(
+ vertices: Float32Array,
+ indices: Uint32Array,
+ flags?: TriMeshFlags,
+ ) {
+ super();
+ this.vertices = vertices;
+ this.indices = indices;
+ this.flags = flags;
+ }
+
+ public intoRaw(): RawShape {
+ return RawShape.trimesh(this.vertices, this.indices, this.flags);
+ }
+}
+
+// #if DIM2
+/**
+ * A shape that is a convex polygon.
+ */
+export class ConvexPolygon extends Shape {
+ readonly type = ShapeType.ConvexPolygon;
+
+ /**
+ * The vertices of the convex polygon.
+ */
+ vertices: Float32Array;
+
+ /**
+ * Do we want to assume the vertices already form a convex hull?
+ */
+ skipConvexHullComputation: boolean;
+
+ /**
+ * Creates a new convex polygon shape.
+ *
+ * @param vertices - The coordinates of the convex polygon's vertices.
+ * @param skipConvexHullComputation - If set to `true`, the input points will
+ * be assumed to form a convex polyline and no convex-hull computation will
+ * be done automatically.
+ */
+ constructor(vertices: Float32Array, skipConvexHullComputation: boolean) {
+ super();
+ this.vertices = vertices;
+ this.skipConvexHullComputation = !!skipConvexHullComputation;
+ }
+
+ public intoRaw(): RawShape {
+ if (this.skipConvexHullComputation) {
+ return RawShape.convexPolyline(this.vertices);
+ } else {
+ return RawShape.convexHull(this.vertices);
+ }
+ }
+}
+
+/**
+ * A shape that is a convex polygon.
+ */
+export class RoundConvexPolygon extends Shape {
+ readonly type = ShapeType.RoundConvexPolygon;
+
+ /**
+ * The vertices of the convex polygon.
+ */
+ vertices: Float32Array;
+
+ /**
+ * Do we want to assume the vertices already form a convex hull?
+ */
+ skipConvexHullComputation: boolean;
+
+ /**
+ * The radius of the convex polygon's rounded edges and vertices.
+ */
+ borderRadius: number;
+
+ /**
+ * Creates a new convex polygon shape.
+ *
+ * @param vertices - The coordinates of the convex polygon's vertices.
+ * @param borderRadius - The radius of the borders of this convex polygon.
+ * @param skipConvexHullComputation - If set to `true`, the input points will
+ * be assumed to form a convex polyline and no convex-hull computation will
+ * be done automatically.
+ */
+ constructor(
+ vertices: Float32Array,
+ borderRadius: number,
+ skipConvexHullComputation: boolean,
+ ) {
+ super();
+ this.vertices = vertices;
+ this.borderRadius = borderRadius;
+ this.skipConvexHullComputation = !!skipConvexHullComputation;
+ }
+
+ public intoRaw(): RawShape {
+ if (this.skipConvexHullComputation) {
+ return RawShape.roundConvexPolyline(
+ this.vertices,
+ this.borderRadius,
+ );
+ } else {
+ return RawShape.roundConvexHull(this.vertices, this.borderRadius);
+ }
+ }
+}
+
+/**
+ * A shape that is a heightfield.
+ */
+export class Heightfield extends Shape {
+ readonly type = ShapeType.HeightField;
+
+ /**
+ * The heights of the heightfield, along its local `y` axis.
+ */
+ heights: Float32Array;
+
+ /**
+ * The heightfield's length along its local `x` axis.
+ */
+ scale: Vector;
+
+ /**
+ * Creates a new heightfield shape.
+ *
+ * @param heights - The heights of the heightfield, along its local `y` axis.
+ * @param scale - The scale factor applied to the heightfield.
+ */
+ constructor(heights: Float32Array, scale: Vector) {
+ super();
+ this.heights = heights;
+ this.scale = scale;
+ }
+
+ public intoRaw(): RawShape {
+ let rawScale = VectorOps.intoRaw(this.scale);
+ let rawShape = RawShape.heightfield(this.heights, rawScale);
+ rawScale.free();
+ return rawShape;
+ }
+}
+
+// #endif
+
+// #if DIM3
+/**
+ * A shape that is a convex polygon.
+ */
+export class ConvexPolyhedron extends Shape {
+ readonly type = ShapeType.ConvexPolyhedron;
+
+ /**
+ * The vertices of the convex polygon.
+ */
+ vertices: Float32Array;
+
+ /**
+ * The indices of the convex polygon.
+ */
+ indices?: Uint32Array | null;
+
+ /**
+ * Creates a new convex polygon shape.
+ *
+ * @param vertices - The coordinates of the convex polygon's vertices.
+ * @param indices - The index buffer of this convex mesh. If this is `null`
+ * or `undefined`, the convex-hull of the input vertices will be computed
+ * automatically. Otherwise, it will be assumed that the mesh you provide
+ * is already convex.
+ */
+ constructor(vertices: Float32Array, indices?: Uint32Array | null) {
+ super();
+ this.vertices = vertices;
+ this.indices = indices;
+ }
+
+ public intoRaw(): RawShape {
+ if (!!this.indices) {
+ return RawShape.convexMesh(this.vertices, this.indices);
+ } else {
+ return RawShape.convexHull(this.vertices);
+ }
+ }
+}
+
+/**
+ * A shape that is a convex polygon.
+ */
+export class RoundConvexPolyhedron extends Shape {
+ readonly type = ShapeType.RoundConvexPolyhedron;
+
+ /**
+ * The vertices of the convex polygon.
+ */
+ vertices: Float32Array;
+
+ /**
+ * The indices of the convex polygon.
+ */
+ indices?: Uint32Array;
+
+ /**
+ * The radius of the convex polyhedron's rounded edges and vertices.
+ */
+ borderRadius: number;
+
+ /**
+ * Creates a new convex polygon shape.
+ *
+ * @param vertices - The coordinates of the convex polygon's vertices.
+ * @param indices - The index buffer of this convex mesh. If this is `null`
+ * or `undefined`, the convex-hull of the input vertices will be computed
+ * automatically. Otherwise, it will be assumed that the mesh you provide
+ * is already convex.
+ * @param borderRadius - The radius of the borders of this convex polyhedron.
+ */
+ constructor(
+ vertices: Float32Array,
+ indices: Uint32Array | null | undefined,
+ borderRadius: number,
+ ) {
+ super();
+ this.vertices = vertices;
+ this.indices = indices;
+ this.borderRadius = borderRadius;
+ }
+
+ public intoRaw(): RawShape {
+ if (!!this.indices) {
+ return RawShape.roundConvexMesh(
+ this.vertices,
+ this.indices,
+ this.borderRadius,
+ );
+ } else {
+ return RawShape.roundConvexHull(this.vertices, this.borderRadius);
+ }
+ }
+}
+
+/**
+ * A shape that is a heightfield.
+ */
+export class Heightfield extends Shape {
+ readonly type = ShapeType.HeightField;
+
+ /**
+ * The number of rows in the heights matrix.
+ */
+ nrows: number;
+
+ /**
+ * The number of columns in the heights matrix.
+ */
+ ncols: number;
+
+ /**
+ * The heights of the heightfield along its local `y` axis,
+ * provided as a matrix stored in column-major order.
+ */
+ heights: Float32Array;
+
+ /**
+ * The dimensions of the heightfield's local `x,z` plane.
+ */
+ scale: Vector;
+
+ /**
+ * Flags applied to the heightfield.
+ */
+ flags: HeightFieldFlags;
+
+ /**
+ * Creates a new heightfield shape.
+ *
+ * @param nrows − The number of rows in the heights matrix.
+ * @param ncols - The number of columns in the heights matrix.
+ * @param heights - The heights of the heightfield along its local `y` axis,
+ * provided as a matrix stored in column-major order.
+ * @param scale - The dimensions of the heightfield's local `x,z` plane.
+ */
+ constructor(
+ nrows: number,
+ ncols: number,
+ heights: Float32Array,
+ scale: Vector,
+ flags?: HeightFieldFlags,
+ ) {
+ super();
+ this.nrows = nrows;
+ this.ncols = ncols;
+ this.heights = heights;
+ this.scale = scale;
+ this.flags = flags;
+ }
+
+ public intoRaw(): RawShape {
+ let rawScale = VectorOps.intoRaw(this.scale);
+ let rawShape = RawShape.heightfield(
+ this.nrows,
+ this.ncols,
+ this.heights,
+ rawScale,
+ this.flags,
+ );
+ rawScale.free();
+ return rawShape;
+ }
+}
+
+/**
+ * A shape that is a 3D cylinder.
+ */
+export class Cylinder extends Shape {
+ readonly type = ShapeType.Cylinder;
+
+ /**
+ * The radius of the cylinder's basis.
+ */
+ radius: number;
+
+ /**
+ * The cylinder's half height, along the `y` axis.
+ */
+ halfHeight: number;
+
+ /**
+ * Creates a new cylinder with the given radius and half-height.
+ * @param halfHeight - The balls half-height along the `y` axis.
+ * @param radius - The balls radius.
+ */
+ constructor(halfHeight: number, radius: number) {
+ super();
+ this.halfHeight = halfHeight;
+ this.radius = radius;
+ }
+
+ public intoRaw(): RawShape {
+ return RawShape.cylinder(this.halfHeight, this.radius);
+ }
+}
+
+/**
+ * A shape that is a 3D cylinder with round corners.
+ */
+export class RoundCylinder extends Shape {
+ readonly type = ShapeType.RoundCylinder;
+
+ /**
+ * The radius of the cylinder's basis.
+ */
+ radius: number;
+
+ /**
+ * The cylinder's half height, along the `y` axis.
+ */
+ halfHeight: number;
+
+ /**
+ * The radius of the cylinder's rounded edges and vertices.
+ */
+ borderRadius: number;
+
+ /**
+ * Creates a new cylinder with the given radius and half-height.
+ * @param halfHeight - The balls half-height along the `y` axis.
+ * @param radius - The balls radius.
+ * @param borderRadius - The radius of the borders of this cylinder.
+ */
+ constructor(halfHeight: number, radius: number, borderRadius: number) {
+ super();
+ this.borderRadius = borderRadius;
+ this.halfHeight = halfHeight;
+ this.radius = radius;
+ }
+
+ public intoRaw(): RawShape {
+ return RawShape.roundCylinder(
+ this.halfHeight,
+ this.radius,
+ this.borderRadius,
+ );
+ }
+}
+
+/**
+ * A shape that is a 3D cone.
+ */
+export class Cone extends Shape {
+ readonly type = ShapeType.Cone;
+
+ /**
+ * The radius of the cone's basis.
+ */
+ radius: number;
+
+ /**
+ * The cone's half height, along the `y` axis.
+ */
+ halfHeight: number;
+
+ /**
+ * Creates a new cone with the given radius and half-height.
+ * @param halfHeight - The balls half-height along the `y` axis.
+ * @param radius - The balls radius.
+ */
+ constructor(halfHeight: number, radius: number) {
+ super();
+ this.halfHeight = halfHeight;
+ this.radius = radius;
+ }
+
+ public intoRaw(): RawShape {
+ return RawShape.cone(this.halfHeight, this.radius);
+ }
+}
+
+/**
+ * A shape that is a 3D cone with round corners.
+ */
+export class RoundCone extends Shape {
+ readonly type = ShapeType.RoundCone;
+
+ /**
+ * The radius of the cone's basis.
+ */
+ radius: number;
+
+ /**
+ * The cone's half height, along the `y` axis.
+ */
+ halfHeight: number;
+
+ /**
+ * The radius of the cylinder's rounded edges and vertices.
+ */
+ borderRadius: number;
+
+ /**
+ * Creates a new cone with the given radius and half-height.
+ * @param halfHeight - The balls half-height along the `y` axis.
+ * @param radius - The balls radius.
+ * @param borderRadius - The radius of the borders of this cone.
+ */
+ constructor(halfHeight: number, radius: number, borderRadius: number) {
+ super();
+ this.halfHeight = halfHeight;
+ this.radius = radius;
+ this.borderRadius = borderRadius;
+ }
+
+ public intoRaw(): RawShape {
+ return RawShape.roundCone(
+ this.halfHeight,
+ this.radius,
+ this.borderRadius,
+ );
+ }
+}
+
+// #endif
diff --git a/typescript/src.ts/geometry/toi.ts b/typescript/src.ts/geometry/toi.ts
new file mode 100644
index 000000000..013c4be38
--- /dev/null
+++ b/typescript/src.ts/geometry/toi.ts
@@ -0,0 +1,163 @@
+import {Collider} from "./collider";
+import {Vector, VectorOps} from "../math";
+
+/**
+ * The intersection between a ray and a collider.
+ */
+export class ShapeCastHit {
+ /**
+ * The time of impact of the two shapes.
+ */
+ time_of_impact: number;
+ /**
+ * The local-space contact point on the first shape, at
+ * the time of impact.
+ */
+ witness1: Vector;
+ /**
+ * The local-space contact point on the second shape, at
+ * the time of impact.
+ */
+ witness2: Vector;
+ /**
+ * The local-space normal on the first shape, at
+ * the time of impact.
+ */
+ normal1: Vector;
+ /**
+ * The local-space normal on the second shape, at
+ * the time of impact.
+ */
+ normal2: Vector;
+
+ constructor(
+ time_of_impact: number,
+ witness1: Vector,
+ witness2: Vector,
+ normal1: Vector,
+ normal2: Vector,
+ ) {
+ this.time_of_impact = time_of_impact;
+ this.witness1 = witness1;
+ this.witness2 = witness2;
+ this.normal1 = normal1;
+ this.normal2 = normal2;
+ }
+
+ public static fromBuffer(
+ collider: Collider,
+ buffer: Float32Array,
+ target?: ShapeCastHit,
+ ): ShapeCastHit {
+ if (!buffer) return null;
+
+ target ??= new ShapeCastHit(
+ 0,
+ VectorOps.zeros(),
+ VectorOps.zeros(),
+ VectorOps.zeros(),
+ VectorOps.zeros(),
+ );
+
+ target.time_of_impact = buffer[0];
+
+ // #if DIM2
+ target.witness1.x = buffer[1];
+ target.witness1.y = buffer[2];
+ target.witness2.x = buffer[3];
+ target.witness2.y = buffer[4];
+ target.normal1.x = buffer[5];
+ target.normal1.y = buffer[6];
+ target.normal2.x = buffer[7];
+ target.normal2.y = buffer[8];
+ // #endif
+
+ // #if DIM3
+ target.witness1.x = buffer[1];
+ target.witness1.y = buffer[2];
+ target.witness1.z = buffer[3];
+ target.witness2.x = buffer[4];
+ target.witness2.y = buffer[5];
+ target.witness2.z = buffer[6];
+ target.normal1.x = buffer[7];
+ target.normal1.y = buffer[8];
+ target.normal1.z = buffer[9];
+ target.normal2.x = buffer[10];
+ target.normal2.y = buffer[11];
+ target.normal2.z = buffer[12];
+ // #endif
+
+ return target;
+ }
+}
+
+/**
+ * The intersection between a ray and a collider.
+ */
+export class ColliderShapeCastHit extends ShapeCastHit {
+ /**
+ * The handle of the collider hit by the ray.
+ */
+ collider: Collider;
+
+ constructor(
+ collider: Collider,
+ time_of_impact: number,
+ witness1: Vector,
+ witness2: Vector,
+ normal1: Vector,
+ normal2: Vector,
+ ) {
+ super(time_of_impact, witness1, witness2, normal1, normal2);
+ this.collider = collider;
+ }
+
+ public static fromBuffer(
+ collider: Collider,
+ buffer: Float32Array,
+ target?: ColliderShapeCastHit,
+ ): ColliderShapeCastHit {
+ if (!buffer) return null;
+
+ target ??= new ColliderShapeCastHit(
+ null,
+ 0,
+ VectorOps.zeros(),
+ VectorOps.zeros(),
+ VectorOps.zeros(),
+ VectorOps.zeros(),
+ );
+
+ target.collider = collider;
+
+ target.time_of_impact = buffer[0];
+
+ // #if DIM2
+ target.witness1.x = buffer[1];
+ target.witness1.y = buffer[2];
+ target.witness2.x = buffer[3];
+ target.witness2.y = buffer[4];
+ target.normal1.x = buffer[5];
+ target.normal1.y = buffer[6];
+ target.normal2.x = buffer[7];
+ target.normal2.y = buffer[8];
+ // #endif
+
+ // #if DIM3
+ target.witness1.x = buffer[1];
+ target.witness1.y = buffer[2];
+ target.witness1.z = buffer[3];
+ target.witness2.x = buffer[4];
+ target.witness2.y = buffer[5];
+ target.witness2.z = buffer[6];
+ target.normal1.x = buffer[7];
+ target.normal1.y = buffer[8];
+ target.normal1.z = buffer[9];
+ target.normal2.x = buffer[10];
+ target.normal2.y = buffer[11];
+ target.normal2.z = buffer[12];
+ // #endif
+
+ return target;
+ }
+}
diff --git a/typescript/src.ts/init.ts b/typescript/src.ts/init.ts
new file mode 100644
index 000000000..e9e66aad7
--- /dev/null
+++ b/typescript/src.ts/init.ts
@@ -0,0 +1,2 @@
+// Placeholder for the `init` function used in rapier-compat.
+export {};
diff --git a/typescript/src.ts/math.ts b/typescript/src.ts/math.ts
new file mode 100644
index 000000000..86eb9e5a6
--- /dev/null
+++ b/typescript/src.ts/math.ts
@@ -0,0 +1,315 @@
+import {RawVector, RawRotation} from "./raw";
+// #if DIM3
+import {RawSdpMatrix3} from "./raw";
+// #endif
+
+// scratchBuffer should be as big as the biggest index Rust tries to set on it.
+export const scratchBuffer = new Float32Array(16);
+
+// #if DIM2
+export interface Vector {
+ x: number;
+ y: number;
+}
+
+/**
+ * A 2D vector.
+ */
+export class Vector2 implements Vector {
+ x: number;
+ y: number;
+
+ constructor(x: number, y: number) {
+ this.x = x;
+ this.y = y;
+ }
+}
+
+export class VectorOps {
+ public static new(x: number, y: number): Vector {
+ return new Vector2(x, y);
+ }
+
+ public static zeros(): Vector {
+ return VectorOps.new(0.0, 0.0);
+ }
+
+ public static fromBuffer(buffer: Float32Array, target?: Vector): Vector {
+ if (!buffer) return null;
+
+ target ??= VectorOps.zeros();
+ target.x = buffer[0];
+ target.y = buffer[1];
+ return target;
+ }
+
+ // FIXME: type ram: RawVector?
+ public static fromRaw(raw: RawVector): Vector {
+ if (!raw) return null;
+
+ let res = VectorOps.new(raw.x, raw.y);
+ raw.free();
+ return res;
+ }
+
+ public static intoRaw(v: Vector): RawVector {
+ return new RawVector(v.x, v.y);
+ }
+
+ public static copy(out: Vector, input: Vector) {
+ out.x = input.x;
+ out.y = input.y;
+ }
+}
+
+/**
+ * A rotation angle in radians.
+ */
+export type Rotation = number;
+
+export class RotationOps {
+ public static identity(): number {
+ return 0.0;
+ }
+
+ public static fromRaw(raw: RawRotation): Rotation {
+ if (!raw) return null;
+
+ let res = raw.angle;
+ raw.free();
+ return res;
+ }
+
+ public static intoRaw(angle: Rotation): RawRotation {
+ return RawRotation.fromAngle(angle);
+ }
+}
+
+// #endif
+
+// #if DIM3
+export interface Vector {
+ x: number;
+ y: number;
+ z: number;
+}
+
+/**
+ * A 3D vector.
+ */
+export class Vector3 implements Vector {
+ x: number;
+ y: number;
+ z: number;
+
+ constructor(x: number, y: number, z: number) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+}
+
+export class VectorOps {
+ public static new(x: number, y: number, z: number): Vector {
+ return new Vector3(x, y, z);
+ }
+
+ public static intoRaw(v: Vector): RawVector {
+ return new RawVector(v.x, v.y, v.z);
+ }
+
+ public static zeros(): Vector {
+ return VectorOps.new(0.0, 0.0, 0.0);
+ }
+
+ public static fromBuffer(buffer: Float32Array, target?: Vector): Vector {
+ if (!buffer) return null;
+
+ target ??= VectorOps.zeros();
+ target.x = buffer[0];
+ target.y = buffer[1];
+ target.z = buffer[2];
+ return target;
+ }
+
+ // FIXME: type ram: RawVector?
+ public static fromRaw(raw: RawVector): Vector {
+ if (!raw) return null;
+
+ let res = VectorOps.new(raw.x, raw.y, raw.z);
+ raw.free();
+ return res;
+ }
+
+ public static copy(out: Vector, input: Vector) {
+ out.x = input.x;
+ out.y = input.y;
+ out.z = input.z;
+ }
+}
+
+export interface Rotation {
+ x: number;
+ y: number;
+ z: number;
+ w: number;
+}
+
+/**
+ * A quaternion.
+ */
+export class Quaternion implements Rotation {
+ x: number;
+ y: number;
+ z: number;
+ w: number;
+
+ constructor(x: number, y: number, z: number, w: number) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.w = w;
+ }
+}
+
+export class RotationOps {
+ public static identity(): Rotation {
+ return new Quaternion(0.0, 0.0, 0.0, 1.0);
+ }
+
+ public static fromBuffer(
+ buffer: Float32Array,
+ target?: Rotation,
+ ): Rotation {
+ if (!buffer) return null;
+
+ target ??= RotationOps.identity();
+ target.x = buffer[0];
+ target.y = buffer[1];
+ target.z = buffer[2];
+ target.w = buffer[3];
+ return target;
+ }
+
+ public static fromRaw(raw: RawRotation): Rotation {
+ if (!raw) return null;
+
+ let res = new Quaternion(raw.x, raw.y, raw.z, raw.w);
+ raw.free();
+ return res;
+ }
+
+ public static intoRaw(rot: Rotation): RawRotation {
+ return new RawRotation(rot.x, rot.y, rot.z, rot.w);
+ }
+
+ public static copy(out: Rotation, input: Rotation) {
+ out.x = input.x;
+ out.y = input.y;
+ out.z = input.z;
+ out.w = input.w;
+ }
+}
+
+/**
+ * A 3D symmetric-positive-definite matrix.
+ */
+export class SdpMatrix3 {
+ /**
+ * Row major list of the upper-triangular part of the symmetric matrix.
+ */
+ elements: Float32Array;
+
+ /**
+ * Matrix element at row 1, column 1.
+ */
+ public get m11(): number {
+ return this.elements[0];
+ }
+
+ /**
+ * Matrix element at row 1, column 2.
+ */
+ public get m12(): number {
+ return this.elements[1];
+ }
+
+ /**
+ * Matrix element at row 2, column 1.
+ */
+ public get m21(): number {
+ return this.m12;
+ }
+
+ /**
+ * Matrix element at row 1, column 3.
+ */
+ public get m13(): number {
+ return this.elements[2];
+ }
+
+ /**
+ * Matrix element at row 3, column 1.
+ */
+ public get m31(): number {
+ return this.m13;
+ }
+
+ /**
+ * Matrix element at row 2, column 2.
+ */
+ public get m22(): number {
+ return this.elements[3];
+ }
+
+ /**
+ * Matrix element at row 2, column 3.
+ */
+ public get m23(): number {
+ return this.elements[4];
+ }
+
+ /**
+ * Matrix element at row 3, column 2.
+ */
+ public get m32(): number {
+ return this.m23;
+ }
+
+ /**
+ * Matrix element at row 3, column 3.
+ */
+ public get m33(): number {
+ return this.elements[5];
+ }
+
+ constructor(elements: Float32Array) {
+ this.elements = elements;
+ }
+}
+
+export class SdpMatrix3Ops {
+ public static fromBuffer(
+ buffer: Float32Array,
+ target?: SdpMatrix3,
+ ): SdpMatrix3 {
+ if (!buffer) return null;
+
+ target ??= new SdpMatrix3(buffer);
+ target.elements[0] = buffer[0];
+ target.elements[1] = buffer[1];
+ target.elements[2] = buffer[2];
+ target.elements[3] = buffer[3];
+ target.elements[4] = buffer[4];
+ target.elements[5] = buffer[5];
+ return target;
+ }
+
+ public static fromRaw(raw: RawSdpMatrix3): SdpMatrix3 {
+ const sdpMatrix3 = new SdpMatrix3(raw.elements());
+ raw.free();
+ return sdpMatrix3;
+ }
+}
+
+// #endif
diff --git a/typescript/src.ts/pipeline/debug_render_pipeline.ts b/typescript/src.ts/pipeline/debug_render_pipeline.ts
new file mode 100644
index 000000000..a377ef5e4
--- /dev/null
+++ b/typescript/src.ts/pipeline/debug_render_pipeline.ts
@@ -0,0 +1,85 @@
+import {RawDebugRenderPipeline} from "../raw";
+import {Vector, VectorOps} from "../math";
+import {
+ IntegrationParameters,
+ IslandManager,
+ ImpulseJointSet,
+ MultibodyJointSet,
+ RigidBodySet,
+} from "../dynamics";
+import {BroadPhase, Collider, ColliderSet, NarrowPhase} from "../geometry";
+import {QueryFilterFlags} from "./query_pipeline";
+
+/**
+ * The vertex and color buffers for debug-rendering the physics scene.
+ */
+export class DebugRenderBuffers {
+ /**
+ * The lines to render. This is a flat array containing all the lines
+ * to render. Each line is described as two consecutive point. Each
+ * point is described as two (in 2D) or three (in 3D) consecutive
+ * floats. For example, in 2D, the array: `[1, 2, 3, 4, 5, 6, 7, 8]`
+ * describes the two segments `[[1, 2], [3, 4]]` and `[[5, 6], [7, 8]]`.
+ */
+ public vertices: Float32Array;
+ /**
+ * The color buffer. There is one color per vertex, and each color
+ * has four consecutive components (in RGBA format).
+ */
+ public colors: Float32Array;
+
+ constructor(vertices: Float32Array, colors: Float32Array) {
+ this.vertices = vertices;
+ this.colors = colors;
+ }
+}
+
+/**
+ * A pipeline for rendering the physics scene.
+ *
+ * To avoid leaking WASM resources, this MUST be freed manually with `debugRenderPipeline.free()`
+ * once you are done using it (and all the rigid-bodies it created).
+ */
+export class DebugRenderPipeline {
+ raw: RawDebugRenderPipeline;
+ public vertices: Float32Array;
+ public colors: Float32Array;
+
+ /**
+ * Release the WASM memory occupied by this serialization pipeline.
+ */
+ free() {
+ if (!!this.raw) {
+ this.raw.free();
+ }
+ this.raw = undefined;
+ this.vertices = undefined;
+ this.colors = undefined;
+ }
+
+ constructor(raw?: RawDebugRenderPipeline) {
+ this.raw = raw || new RawDebugRenderPipeline();
+ }
+
+ public render(
+ bodies: RigidBodySet,
+ colliders: ColliderSet,
+ impulse_joints: ImpulseJointSet,
+ multibody_joints: MultibodyJointSet,
+ narrow_phase: NarrowPhase,
+ filterFlags?: QueryFilterFlags,
+ filterPredicate?: (collider: Collider) => boolean,
+ ) {
+ this.raw.render(
+ bodies.raw,
+ colliders.raw,
+ impulse_joints.raw,
+ multibody_joints.raw,
+ narrow_phase.raw,
+ filterFlags,
+ colliders.castClosure(filterPredicate),
+ );
+ this.vertices = this.raw.vertices();
+ this.colors = this.raw.colors();
+ }
+}
diff --git a/typescript/src.ts/pipeline/event_queue.ts b/typescript/src.ts/pipeline/event_queue.ts
new file mode 100644
index 000000000..1269b7a8f
--- /dev/null
+++ b/typescript/src.ts/pipeline/event_queue.ts
@@ -0,0 +1,160 @@
+import {RawContactForceEvent, RawEventQueue} from "../raw";
+import {RigidBodyHandle} from "../dynamics";
+import {Collider, ColliderHandle} from "../geometry";
+import {Vector, VectorOps, scratchBuffer} from "../math";
+
+/**
+ * Flags indicating what events are enabled for colliders.
+ */
+export enum ActiveEvents {
+ NONE = 0,
+ /**
+ * Enable collision events.
+ */
+ COLLISION_EVENTS = 0b0001,
+ /**
+ * Enable contact force events.
+ */
+ CONTACT_FORCE_EVENTS = 0b0010,
+}
+
+/**
+ * Event occurring when the sum of the magnitudes of the
+ * contact forces between two colliders exceed a threshold.
+ *
+ * This object should **not** be stored anywhere. Its properties can only be
+ * read from within the closure given to `EventHandler.drainContactForceEvents`.
+ */
+export class TempContactForceEvent {
+ raw: RawContactForceEvent;
+
+ public free() {
+ if (!!this.raw) {
+ this.raw.free();
+ }
+ this.raw = undefined;
+ }
+
+ /**
+ * The first collider involved in the contact.
+ */
+ public collider1(): ColliderHandle {
+ return this.raw.collider1();
+ }
+
+ /**
+ * The second collider involved in the contact.
+ */
+ public collider2(): ColliderHandle {
+ return this.raw.collider2();
+ }
+
+ /**
+ * The sum of all the forces between the two colliders.
+ */
+ public totalForce(target?: Vector): Vector {
+ this.raw.total_force(scratchBuffer);
+ return VectorOps.fromBuffer(scratchBuffer, target);
+ }
+
+ /**
+ * The sum of the magnitudes of each force between the two colliders.
+ *
+ * Note that this is **not** the same as the magnitude of `self.total_force`.
+ * Here we are summing the magnitude of all the forces, instead of taking
+ * the magnitude of their sum.
+ */
+ public totalForceMagnitude(): number {
+ return this.raw.total_force_magnitude();
+ }
+
+ /**
+ * The world-space (unit) direction of the force with strongest magnitude.
+ */
+ public maxForceDirection(target?: Vector): Vector {
+ this.raw.max_force_direction(scratchBuffer);
+ return VectorOps.fromBuffer(scratchBuffer, target);
+ }
+
+ /**
+ * The magnitude of the largest force at a contact point of this contact pair.
+ */
+ public maxForceMagnitude(): number {
+ return this.raw.max_force_magnitude();
+ }
+}
+
+/**
+ * A structure responsible for collecting events generated
+ * by the physics engine.
+ *
+ * To avoid leaking WASM resources, this MUST be freed manually with `eventQueue.free()`
+ * once you are done using it.
+ */
+export class EventQueue {
+ raw: RawEventQueue;
+
+ /**
+ * Creates a new event collector.
+ *
+ * @param autoDrain -setting this to `true` is strongly recommended. If true, the collector will
+ * be automatically drained before each `world.step(collector)`. If false, the collector will
+ * keep all events in memory unless it is manually drained/cleared; this may lead to unbounded use of
+ * RAM if no drain is performed.
+ */
+ constructor(autoDrain: boolean, raw?: RawEventQueue) {
+ this.raw = raw || new RawEventQueue(autoDrain);
+ }
+
+ /**
+ * Release the WASM memory occupied by this event-queue.
+ */
+ public free() {
+ if (!!this.raw) {
+ this.raw.free();
+ }
+ this.raw = undefined;
+ }
+
+ /**
+ * Applies the given javascript closure on each collision event of this collector, then clear
+ * the internal collision event buffer.
+ *
+ * @param f - JavaScript closure applied to each collision event. The
+ * closure must take three arguments: two integers representing the handles of the colliders
+ * involved in the collision, and a boolean indicating if the collision started (true) or stopped
+ * (false).
+ */
+ public drainCollisionEvents(
+ f: (
+ handle1: ColliderHandle,
+ handle2: ColliderHandle,
+ started: boolean,
+ ) => void,
+ ) {
+ this.raw.drainCollisionEvents(f);
+ }
+
+ /**
+ * Applies the given javascript closure on each contact force event of this collector, then clear
+ * the internal collision event buffer.
+ *
+ * @param f - JavaScript closure applied to each collision event. The
+ * closure must take one `TempContactForceEvent` argument.
+ */
+ public drainContactForceEvents(f: (event: TempContactForceEvent) => void) {
+ let event = new TempContactForceEvent();
+ this.raw.drainContactForceEvents((raw: RawContactForceEvent) => {
+ event.raw = raw;
+ f(event);
+ event.free();
+ });
+ }
+
+ /**
+ * Removes all events contained by this collector
+ */
+ public clear() {
+ this.raw.clear();
+ }
+}
diff --git a/typescript/src.ts/pipeline/index.ts b/typescript/src.ts/pipeline/index.ts
new file mode 100644
index 000000000..092c1a596
--- /dev/null
+++ b/typescript/src.ts/pipeline/index.ts
@@ -0,0 +1,7 @@
+export * from "./world";
+export * from "./physics_pipeline";
+export * from "./serialization_pipeline";
+export * from "./event_queue";
+export * from "./physics_hooks";
+export * from "./debug_render_pipeline";
+export * from "./query_pipeline";
diff --git a/typescript/src.ts/pipeline/physics_hooks.ts b/typescript/src.ts/pipeline/physics_hooks.ts
new file mode 100644
index 000000000..20e12ad98
--- /dev/null
+++ b/typescript/src.ts/pipeline/physics_hooks.ts
@@ -0,0 +1,54 @@
+import {RigidBodyHandle} from "../dynamics";
+import {ColliderHandle} from "../geometry";
+
+export enum ActiveHooks {
+ NONE = 0,
+ FILTER_CONTACT_PAIRS = 0b0001,
+ FILTER_INTERSECTION_PAIRS = 0b0010,
+ // MODIFY_SOLVER_CONTACTS = 0b0100, /* Not supported yet in JS. */
+}
+
+export enum SolverFlags {
+ EMPTY = 0b000,
+ COMPUTE_IMPULSE = 0b001,
+}
+
+export interface PhysicsHooks {
+ /**
+ * Function that determines if contacts computation should happen between two colliders, and how the
+ * constraints solver should behave for these contacts.
+ *
+ * This will only be executed and taken into account if at least one of the involved colliders contains the
+ * `ActiveHooks.FILTER_CONTACT_PAIR` flag in its active hooks.
+ *
+ * @param collider1 − Handle of the first collider involved in the potential contact.
+ * @param collider2 − Handle of the second collider involved in the potential contact.
+ * @param body1 − Handle of the first body involved in the potential contact.
+ * @param body2 − Handle of the second body involved in the potential contact.
+ */
+ filterContactPair(
+ collider1: ColliderHandle,
+ collider2: ColliderHandle,
+ body1: RigidBodyHandle,
+ body2: RigidBodyHandle,
+ ): SolverFlags | null;
+
+ /**
+ * Function that determines if intersection computation should happen between two colliders (where at least
+ * one is a sensor).
+ *
+ * This will only be executed and taken into account if `one of the involved colliders contains the
+ * `ActiveHooks.FILTER_INTERSECTION_PAIR` flag in its active hooks.
+ *
+ * @param collider1 − Handle of the first collider involved in the potential contact.
+ * @param collider2 − Handle of the second collider involved in the potential contact.
+ * @param body1 − Handle of the first body involved in the potential contact.
+ * @param body2 − Handle of the second body involved in the potential contact.
+ */
+ filterIntersectionPair(
+ collider1: ColliderHandle,
+ collider2: ColliderHandle,
+ body1: RigidBodyHandle,
+ body2: RigidBodyHandle,
+ ): boolean;
+}
diff --git a/typescript/src.ts/pipeline/physics_pipeline.ts b/typescript/src.ts/pipeline/physics_pipeline.ts
new file mode 100644
index 000000000..a3319205c
--- /dev/null
+++ b/typescript/src.ts/pipeline/physics_pipeline.ts
@@ -0,0 +1,85 @@
+import {RawPhysicsPipeline} from "../raw";
+import {Vector, VectorOps} from "../math";
+import {
+ IntegrationParameters,
+ ImpulseJointSet,
+ MultibodyJointSet,
+ RigidBodyHandle,
+ RigidBodySet,
+ CCDSolver,
+ IslandManager,
+} from "../dynamics";
+import {
+ BroadPhase,
+ ColliderHandle,
+ ColliderSet,
+ NarrowPhase,
+} from "../geometry";
+import {EventQueue} from "./event_queue";
+import {PhysicsHooks} from "./physics_hooks";
+
+export class PhysicsPipeline {
+ raw: RawPhysicsPipeline;
+
+ public free() {
+ if (!!this.raw) {
+ this.raw.free();
+ }
+ this.raw = undefined;
+ }
+
+ constructor(raw?: RawPhysicsPipeline) {
+ this.raw = raw || new RawPhysicsPipeline();
+ }
+
+ public step(
+ gravity: Vector,
+ integrationParameters: IntegrationParameters,
+ islands: IslandManager,
+ broadPhase: BroadPhase,
+ narrowPhase: NarrowPhase,
+ bodies: RigidBodySet,
+ colliders: ColliderSet,
+ impulseJoints: ImpulseJointSet,
+ multibodyJoints: MultibodyJointSet,
+ ccdSolver: CCDSolver,
+ eventQueue?: EventQueue,
+ hooks?: PhysicsHooks,
+ ) {
+ let rawG = VectorOps.intoRaw(gravity);
+
+ if (!!eventQueue) {
+ this.raw.stepWithEvents(
+ rawG,
+ integrationParameters.raw,
+ islands.raw,
+ broadPhase.raw,
+ narrowPhase.raw,
+ bodies.raw,
+ colliders.raw,
+ impulseJoints.raw,
+ multibodyJoints.raw,
+ ccdSolver.raw,
+ eventQueue.raw,
+ hooks,
+ !!hooks ? hooks.filterContactPair : null,
+ !!hooks ? hooks.filterIntersectionPair : null,
+ );
+ } else {
+ this.raw.step(
+ rawG,
+ integrationParameters.raw,
+ islands.raw,
+ broadPhase.raw,
+ narrowPhase.raw,
+ bodies.raw,
+ colliders.raw,
+ impulseJoints.raw,
+ multibodyJoints.raw,
+ ccdSolver.raw,
+ );
+ }
+
+ rawG.free();
+ }
+}
diff --git a/typescript/src.ts/pipeline/query_pipeline.ts b/typescript/src.ts/pipeline/query_pipeline.ts
new file mode 100644
index 000000000..5610ff31f
--- /dev/null
+++ b/typescript/src.ts/pipeline/query_pipeline.ts
@@ -0,0 +1,57 @@
+import {RawRayColliderIntersection} from "../raw";
+import {
+ ColliderHandle,
+ ColliderSet,
+ InteractionGroups,
+ PointColliderProjection,
+ Ray,
+ RayColliderIntersection,
+ RayColliderHit,
+ Shape,
+ ColliderShapeCastHit,
+} from "../geometry";
+import {IslandManager, RigidBodyHandle, RigidBodySet} from "../dynamics";
+import {Rotation, RotationOps, Vector, VectorOps} from "../math";
+
+// NOTE: must match the bits in the QueryFilterFlags on the Rust side.
+/**
+ * Flags for excluding whole sets of colliders from a scene query.
+ */
+export enum QueryFilterFlags {
+ /**
+ * Exclude from the query any collider attached to a fixed rigid-body and colliders with no rigid-body attached.
+ */
+ EXCLUDE_FIXED = 0b0000_0001,
+ /**
+ * Exclude from the query any collider attached to a dynamic rigid-body.
+ */
+ EXCLUDE_KINEMATIC = 0b0000_0010,
+ /**
+ * Exclude from the query any collider attached to a kinematic rigid-body.
+ */
+ EXCLUDE_DYNAMIC = 0b0000_0100,
+ /**
+ * Exclude from the query any collider that is a sensor.
+ */
+ EXCLUDE_SENSORS = 0b0000_1000,
+ /**
+ * Exclude from the query any collider that is not a sensor.
+ */
+ EXCLUDE_SOLIDS = 0b0001_0000,
+ /**
+ * Excludes all colliders not attached to a dynamic rigid-body.
+ */
+ ONLY_DYNAMIC = QueryFilterFlags.EXCLUDE_FIXED |
+ QueryFilterFlags.EXCLUDE_KINEMATIC,
+ /**
+ * Excludes all colliders not attached to a kinematic rigid-body.
+ */
+ ONLY_KINEMATIC = QueryFilterFlags.EXCLUDE_DYNAMIC |
+ QueryFilterFlags.EXCLUDE_FIXED,
+ /**
+ * Exclude all colliders attached to a non-fixed rigid-body
+ * (this will not exclude colliders not attached to any rigid-body).
+ */
+ ONLY_FIXED = QueryFilterFlags.EXCLUDE_DYNAMIC |
+ QueryFilterFlags.EXCLUDE_KINEMATIC,
+}
diff --git a/typescript/src.ts/pipeline/serialization_pipeline.ts b/typescript/src.ts/pipeline/serialization_pipeline.ts
new file mode 100644
index 000000000..87fde398c
--- /dev/null
+++ b/typescript/src.ts/pipeline/serialization_pipeline.ts
@@ -0,0 +1,84 @@
+import {RawSerializationPipeline} from "../raw";
+import {Vector, VectorOps} from "../math";
+import {
+ IntegrationParameters,
+ IslandManager,
+ ImpulseJointSet,
+ MultibodyJointSet,
+ RigidBodySet,
+} from "../dynamics";
+import {BroadPhase, ColliderSet, NarrowPhase} from "../geometry";
+import {World} from "./world";
+
+/**
+ * A pipeline for serializing the physics scene.
+ *
+ * To avoid leaking WASM resources, this MUST be freed manually with `serializationPipeline.free()`
+ * once you are done using it (and all the rigid-bodies it created).
+ */
+export class SerializationPipeline {
+ raw: RawSerializationPipeline;
+
+ /**
+ * Release the WASM memory occupied by this serialization pipeline.
+ */
+ free() {
+ if (!!this.raw) {
+ this.raw.free();
+ }
+ this.raw = undefined;
+ }
+
+ constructor(raw?: RawSerializationPipeline) {
+ this.raw = raw || new RawSerializationPipeline();
+ }
+
+ /**
+ * Serialize a complete physics state into a single byte array.
+ * @param gravity - The current gravity affecting the simulation.
+ * @param integrationParameters - The integration parameters of the simulation.
+ * @param broadPhase - The broad-phase of the simulation.
+ * @param narrowPhase - The narrow-phase of the simulation.
+ * @param bodies - The rigid-bodies taking part into the simulation.
+ * @param colliders - The colliders taking part into the simulation.
+ * @param impulseJoints - The impulse joints taking part into the simulation.
+ * @param multibodyJoints - The multibody joints taking part into the simulation.
+ */
+ public serializeAll(
+ gravity: Vector,
+ integrationParameters: IntegrationParameters,
+ islands: IslandManager,
+ broadPhase: BroadPhase,
+ narrowPhase: NarrowPhase,
+ bodies: RigidBodySet,
+ colliders: ColliderSet,
+ impulseJoints: ImpulseJointSet,
+ multibodyJoints: MultibodyJointSet,
+ ): Uint8Array {
+ let rawGra = VectorOps.intoRaw(gravity);
+
+ const res = this.raw.serializeAll(
+ rawGra,
+ integrationParameters.raw,
+ islands.raw,
+ broadPhase.raw,
+ narrowPhase.raw,
+ bodies.raw,
+ colliders.raw,
+ impulseJoints.raw,
+ multibodyJoints.raw,
+ );
+ rawGra.free();
+
+ return res;
+ }
+
+ /**
+ * Deserialize the complete physics state from a single byte array.
+ *
+ * @param data - The byte array to deserialize.
+ */
+ public deserializeAll(data: Uint8Array): World {
+ return World.fromRaw(this.raw.deserializeAll(data));
+ }
+}
diff --git a/typescript/src.ts/pipeline/world.ts b/typescript/src.ts/pipeline/world.ts
new file mode 100644
index 000000000..9ee856161
--- /dev/null
+++ b/typescript/src.ts/pipeline/world.ts
@@ -0,0 +1,1312 @@
+import {
+ RawBroadPhase,
+ RawCCDSolver,
+ RawColliderSet,
+ RawDeserializedWorld,
+ RawIntegrationParameters,
+ RawIslandManager,
+ RawImpulseJointSet,
+ RawMultibodyJointSet,
+ RawNarrowPhase,
+ RawPhysicsPipeline,
+ RawRigidBodySet,
+ RawSerializationPipeline,
+ RawDebugRenderPipeline,
+} from "../raw";
+
+import {
+ BroadPhase,
+ Collider,
+ ColliderDesc,
+ ColliderHandle,
+ ColliderSet,
+ InteractionGroups,
+ NarrowPhase,
+ PointColliderProjection,
+ Ray,
+ RayColliderIntersection,
+ RayColliderHit,
+ Shape,
+ ColliderShapeCastHit,
+ TempContactManifold,
+} from "../geometry";
+import {
+ CCDSolver,
+ IntegrationParameters,
+ IslandManager,
+ ImpulseJoint,
+ ImpulseJointHandle,
+ MultibodyJoint,
+ MultibodyJointHandle,
+ JointData,
+ ImpulseJointSet,
+ MultibodyJointSet,
+ RigidBody,
+ RigidBodyDesc,
+ RigidBodyHandle,
+ RigidBodySet,
+} from "../dynamics";
+import {Rotation, Vector, VectorOps} from "../math";
+import {PhysicsPipeline} from "./physics_pipeline";
+import {QueryFilterFlags} from "./query_pipeline";
+import {SerializationPipeline} from "./serialization_pipeline";
+import {EventQueue} from "./event_queue";
+import {PhysicsHooks} from "./physics_hooks";
+import {DebugRenderBuffers, DebugRenderPipeline} from "./debug_render_pipeline";
+import {
+ KinematicCharacterController,
+ PidAxesMask,
+ PidController,
+} from "../control";
+import {Coarena} from "../coarena";
+
+// #if DIM3
+import {DynamicRayCastVehicleController} from "../control";
+
+// #endif
+
+/**
+ * The physics world.
+ *
+ * This contains all the data-structures necessary for creating and simulating
+ * bodies with contacts, joints, and external forces.
+ */
+export class World {
+ public gravity: Vector;
+ integrationParameters: IntegrationParameters;
+ islands: IslandManager;
+ broadPhase: BroadPhase;
+ narrowPhase: NarrowPhase;
+ bodies: RigidBodySet;
+ colliders: ColliderSet;
+ impulseJoints: ImpulseJointSet;
+ multibodyJoints: MultibodyJointSet;
+ ccdSolver: CCDSolver;
+ physicsPipeline: PhysicsPipeline;
+ serializationPipeline: SerializationPipeline;
+ debugRenderPipeline: DebugRenderPipeline;
+ characterControllers: Set;
+ pidControllers: Set;
+
+ // #if DIM3
+ vehicleControllers: Set;
+
+ // #endif
+
+ /**
+ * Release the WASM memory occupied by this physics world.
+ *
+ * All the fields of this physics world will be freed as well,
+ * so there is no need to call their `.free()` methods individually.
+ */
+ public free() {
+ this.integrationParameters.free();
+ this.islands.free();
+ this.broadPhase.free();
+ this.narrowPhase.free();
+ this.bodies.free();
+ this.colliders.free();
+ this.impulseJoints.free();
+ this.multibodyJoints.free();
+ this.ccdSolver.free();
+ this.physicsPipeline.free();
+ this.serializationPipeline.free();
+ this.debugRenderPipeline.free();
+ this.characterControllers.forEach((controller) => controller.free());
+ this.pidControllers.forEach((controller) => controller.free());
+
+ // #if DIM3
+ this.vehicleControllers.forEach((controller) => controller.free());
+ // #endif
+
+ this.integrationParameters = undefined;
+ this.islands = undefined;
+ this.broadPhase = undefined;
+ this.narrowPhase = undefined;
+ this.bodies = undefined;
+ this.colliders = undefined;
+ this.ccdSolver = undefined;
+ this.impulseJoints = undefined;
+ this.multibodyJoints = undefined;
+ this.physicsPipeline = undefined;
+ this.serializationPipeline = undefined;
+ this.debugRenderPipeline = undefined;
+ this.characterControllers = undefined;
+ this.pidControllers = undefined;
+
+ // #if DIM3
+ this.vehicleControllers = undefined;
+ // #endif
+ }
+
+ constructor(
+ gravity: Vector,
+ rawIntegrationParameters?: RawIntegrationParameters,
+ rawIslands?: RawIslandManager,
+ rawBroadPhase?: RawBroadPhase,
+ rawNarrowPhase?: RawNarrowPhase,
+ rawBodies?: RawRigidBodySet,
+ rawColliders?: RawColliderSet,
+ rawImpulseJoints?: RawImpulseJointSet,
+ rawMultibodyJoints?: RawMultibodyJointSet,
+ rawCCDSolver?: RawCCDSolver,
+ rawPhysicsPipeline?: RawPhysicsPipeline,
+ rawSerializationPipeline?: RawSerializationPipeline,
+ rawDebugRenderPipeline?: RawDebugRenderPipeline,
+ ) {
+ this.gravity = gravity;
+ this.integrationParameters = new IntegrationParameters(
+ rawIntegrationParameters,
+ );
+ this.islands = new IslandManager(rawIslands);
+ this.broadPhase = new BroadPhase(rawBroadPhase);
+ this.narrowPhase = new NarrowPhase(rawNarrowPhase);
+ this.bodies = new RigidBodySet(rawBodies);
+ this.colliders = new ColliderSet(rawColliders);
+ this.impulseJoints = new ImpulseJointSet(rawImpulseJoints);
+ this.multibodyJoints = new MultibodyJointSet(rawMultibodyJoints);
+ this.ccdSolver = new CCDSolver(rawCCDSolver);
+ this.physicsPipeline = new PhysicsPipeline(rawPhysicsPipeline);
+ this.serializationPipeline = new SerializationPipeline(
+ rawSerializationPipeline,
+ );
+ this.debugRenderPipeline = new DebugRenderPipeline(
+ rawDebugRenderPipeline,
+ );
+ this.characterControllers = new Set();
+ this.pidControllers = new Set();
+
+ // #if DIM3
+ this.vehicleControllers = new Set();
+ // #endif
+
+ this.impulseJoints.finalizeDeserialization(this.bodies);
+ this.bodies.finalizeDeserialization(this.colliders);
+ this.colliders.finalizeDeserialization(this.bodies);
+ }
+
+ public static fromRaw(raw: RawDeserializedWorld): World {
+ if (!raw) return null;
+
+ return new World(
+ VectorOps.fromRaw(raw.takeGravity()),
+ raw.takeIntegrationParameters(),
+ raw.takeIslandManager(),
+ raw.takeBroadPhase(),
+ raw.takeNarrowPhase(),
+ raw.takeBodies(),
+ raw.takeColliders(),
+ raw.takeImpulseJoints(),
+ raw.takeMultibodyJoints(),
+ );
+ }
+
+ /**
+ * Takes a snapshot of this world.
+ *
+ * Use `World.restoreSnapshot` to create a new physics world with a state identical to
+ * the state when `.takeSnapshot()` is called.
+ */
+ public takeSnapshot(): Uint8Array {
+ return this.serializationPipeline.serializeAll(
+ this.gravity,
+ this.integrationParameters,
+ this.islands,
+ this.broadPhase,
+ this.narrowPhase,
+ this.bodies,
+ this.colliders,
+ this.impulseJoints,
+ this.multibodyJoints,
+ );
+ }
+
+ /**
+ * Creates a new physics world from a snapshot.
+ *
+ * This new physics world will be an identical copy of the snapshoted physics world.
+ */
+ public static restoreSnapshot(data: Uint8Array): World {
+ let deser = new SerializationPipeline();
+ return deser.deserializeAll(data);
+ }
+
+ /**
+ * Computes all the lines (and their colors) needed to render the scene.
+ *
+ * @param filterFlags - Flags for excluding whole subsets of colliders from rendering.
+ * @param filterPredicate - Any collider for which this closure returns `false` will be excluded from the
+ * debug rendering.
+ */
+ public debugRender(
+ filterFlags?: QueryFilterFlags,
+ filterPredicate?: (collider: Collider) => boolean,
+ ): DebugRenderBuffers {
+ this.debugRenderPipeline.render(
+ this.bodies,
+ this.colliders,
+ this.impulseJoints,
+ this.multibodyJoints,
+ this.narrowPhase,
+ filterFlags,
+ filterPredicate,
+ );
+ return new DebugRenderBuffers(
+ this.debugRenderPipeline.vertices,
+ this.debugRenderPipeline.colors,
+ );
+ }
+
+ /**
+ * Advance the simulation by one time step.
+ *
+ * All events generated by the physics engine are ignored.
+ *
+ * @param EventQueue - (optional) structure responsible for collecting
+ * events generated by the physics engine.
+ */
+ public step(eventQueue?: EventQueue, hooks?: PhysicsHooks) {
+ this.physicsPipeline.step(
+ this.gravity,
+ this.integrationParameters,
+ this.islands,
+ this.broadPhase,
+ this.narrowPhase,
+ this.bodies,
+ this.colliders,
+ this.impulseJoints,
+ this.multibodyJoints,
+ this.ccdSolver,
+ eventQueue,
+ hooks,
+ );
+ }
+
+ /**
+ * Update colliders positions after rigid-bodies moved.
+ *
+ * When a rigid-body moves, the positions of the colliders attached to it need to be updated. This update is
+ * generally automatically done at the beginning and the end of each simulation step with World.step.
+ * If the positions need to be updated without running a simulation step this method can be called manually.
+ */
+ public propagateModifiedBodyPositionsToColliders() {
+ this.bodies.raw.propagateModifiedBodyPositionsToColliders(
+ this.colliders.raw,
+ );
+ }
+
+ // TODO: This needs to trigger a broad-phase update but without emitting collision events?
+ // /**
+ // * Ensure subsequent scene queries take into account the collider positions set before this method is called.
+ // *
+ // * This does not step the physics simulation forward.
+ // */
+ // public updateSceneQueries() {
+ // this.propagateModifiedBodyPositionsToColliders();
+ // this.queryPipeline.update(this.colliders);
+ // }
+
+ /**
+ * The current simulation timestep.
+ */
+ get timestep(): number {
+ return this.integrationParameters.dt;
+ }
+
+ /**
+ * Sets the new simulation timestep.
+ *
+ * The simulation timestep governs by how much the physics state of the world will
+ * be integrated. A simulation timestep should:
+ * - be as small as possible. Typical values evolve around 0.016 (assuming the chosen unit is milliseconds,
+ * corresponds to the time between two frames of a game running at 60FPS).
+ * - not vary too much during the course of the simulation. A timestep with large variations may
+ * cause instabilities in the simulation.
+ *
+ * @param dt - The timestep length, in seconds.
+ */
+ set timestep(dt: number) {
+ this.integrationParameters.dt = dt;
+ }
+
+ /**
+ * The approximate size of most dynamic objects in the scene.
+ *
+ * See the documentation of the `World.lengthUnit` setter for further details.
+ */
+ get lengthUnit(): number {
+ return this.integrationParameters.lengthUnit;
+ }
+
+ /**
+ * The approximate size of most dynamic objects in the scene.
+ *
+ * This value is used internally to estimate some length-based tolerance. In particular, the
+ * values `IntegrationParameters.allowedLinearError`,
+ * `IntegrationParameters.maxPenetrationCorrection`,
+ * `IntegrationParameters.predictionDistance`, `RigidBodyActivation.linearThreshold`
+ * are scaled by this value implicitly.
+ *
+ * This value can be understood as the number of units-per-meter in your physical world compared
+ * to a human-sized world in meter. For example, in a 2d game, if your typical object size is 100
+ * pixels, set the `[`Self::length_unit`]` parameter to 100.0. The physics engine will interpret
+ * it as if 100 pixels is equivalent to 1 meter in its various internal threshold.
+ * (default `1.0`).
+ */
+ set lengthUnit(unitsPerMeter: number) {
+ this.integrationParameters.lengthUnit = unitsPerMeter;
+ }
+
+ /**
+ * The number of solver iterations run by the constraints solver for calculating forces (default: `4`).
+ */
+ get numSolverIterations(): number {
+ return this.integrationParameters.numSolverIterations;
+ }
+
+ /**
+ * Sets the number of solver iterations run by the constraints solver for calculating forces (default: `4`).
+ *
+ * The greater this value is, the most rigid and realistic the physics simulation will be.
+ * However a greater number of iterations is more computationally intensive.
+ *
+ * @param niter - The new number of solver iterations.
+ */
+ set numSolverIterations(niter: number) {
+ this.integrationParameters.numSolverIterations = niter;
+ }
+
+ /**
+ * Number of internal Project Gauss Seidel (PGS) iterations run at each solver iteration (default: `1`).
+ */
+ get numInternalPgsIterations(): number {
+ return this.integrationParameters.numInternalPgsIterations;
+ }
+
+ /**
+ * Sets the Number of internal Project Gauss Seidel (PGS) iterations run at each solver iteration (default: `1`).
+ *
+ * Increasing this parameter will improve stability of the simulation. It will have a lesser effect than
+ * increasing `numSolverIterations` but is also less computationally expensive.
+ *
+ * @param niter - The new number of internal PGS iterations.
+ */
+ set numInternalPgsIterations(niter: number) {
+ this.integrationParameters.numInternalPgsIterations = niter;
+ }
+
+ /**
+ * The number of substeps continuous collision-detection can run (default: `1`).
+ */
+ get maxCcdSubsteps(): number {
+ return this.integrationParameters.maxCcdSubsteps;
+ }
+
+ /**
+ * Sets the number of substeps continuous collision-detection can run (default: `1`).
+ *
+ * CCD operates using a "motion clamping" mechanism where all fast-moving object trajectories will
+ * be truncated to their first impact on their path. The number of CCD substeps beyond 1 indicate how
+ * many times that trajectory will be updated and continued after a hit. This can results in smoother
+ * paths, but at a significant computational cost.
+ *
+ * @param niter - The new maximum number of CCD substeps. Setting to `0` disables CCD entirely.
+ */
+ set maxCcdSubsteps(substeps: number) {
+ this.integrationParameters.maxCcdSubsteps = substeps;
+ }
+
+ /**
+ * Creates a new rigid-body from the given rigid-body descriptor.
+ *
+ * @param body - The description of the rigid-body to create.
+ */
+ public createRigidBody(body: RigidBodyDesc): RigidBody {
+ return this.bodies.createRigidBody(this.colliders, body);
+ }
+
+ /**
+ * Creates a new character controller.
+ *
+ * @param offset - The artificial gap added between the character’s chape and its environment.
+ */
+ public createCharacterController(
+ offset: number,
+ ): KinematicCharacterController {
+ let controller = new KinematicCharacterController(
+ offset,
+ this.integrationParameters,
+ this.broadPhase,
+ this.narrowPhase,
+ this.bodies,
+ this.colliders,
+ );
+ this.characterControllers.add(controller);
+ return controller;
+ }
+
+ /**
+ * Removes a character controller from this world.
+ *
+ * @param controller - The character controller to remove.
+ */
+ public removeCharacterController(controller: KinematicCharacterController) {
+ this.characterControllers.delete(controller);
+ controller.free();
+ }
+
+ /**
+ * Creates a new PID (Proportional-Integral-Derivative) controller.
+ *
+ * @param kp - The Proportional gain applied to the instantaneous linear position errors.
+ * This is usually set to a multiple of the inverse of simulation step time
+ * (e.g. `60` if the delta-time is `1.0 / 60.0`).
+ * @param ki - The linear gain applied to the Integral part of the PID controller.
+ * @param kd - The Derivative gain applied to the instantaneous linear velocity errors.
+ * This is usually set to a value in `[0.0, 1.0]` where `0.0` implies no damping
+ * (no correction of velocity errors) and `1.0` implies complete damping (velocity errors
+ * are corrected in a single simulation step).
+ * @param axes - The axes affected by this controller.
+ * Only coordinate axes with a bit flags set to `true` will be taken into
+ * account when calculating the errors and corrections.
+ */
+ public createPidController(
+ kp: number,
+ ki: number,
+ kd: number,
+ axes: PidAxesMask,
+ ): PidController {
+ let controller = new PidController(
+ this.integrationParameters,
+ this.bodies,
+ kp,
+ ki,
+ kd,
+ axes,
+ );
+ this.pidControllers.add(controller);
+ return controller;
+ }
+
+ /**
+ * Removes a PID controller from this world.
+ *
+ * @param controller - The PID controller to remove.
+ */
+ public removePidController(controller: PidController) {
+ this.pidControllers.delete(controller);
+ controller.free();
+ }
+
+ // #if DIM3
+ /**
+ * Creates a new vehicle controller.
+ *
+ * @param chassis - The rigid-body used as the chassis of the vehicle controller. When the vehicle
+ * controller is updated, it will change directly the rigid-body’s velocity. This
+ * rigid-body must be a dynamic or kinematic-velocity-based rigid-body.
+ */
+ public createVehicleController(
+ chassis: RigidBody,
+ ): DynamicRayCastVehicleController {
+ let controller = new DynamicRayCastVehicleController(
+ chassis,
+ this.broadPhase,
+ this.narrowPhase,
+ this.bodies,
+ this.colliders,
+ );
+ this.vehicleControllers.add(controller);
+ return controller;
+ }
+
+ /**
+ * Removes a vehicle controller from this world.
+ *
+ * @param controller - The vehicle controller to remove.
+ */
+ public removeVehicleController(
+ controller: DynamicRayCastVehicleController,
+ ) {
+ this.vehicleControllers.delete(controller);
+ controller.free();
+ }
+
+ // #endif
+
+ /**
+ * Creates a new collider.
+ *
+ * @param desc - The description of the collider.
+ * @param parent - The rigid-body this collider is attached to.
+ */
+ public createCollider(desc: ColliderDesc, parent?: RigidBody): Collider {
+ let parentHandle = parent ? parent.handle : undefined;
+ return this.colliders.createCollider(this.bodies, desc, parentHandle);
+ }
+
+ /**
+ * Creates a new impulse joint from the given joint descriptor.
+ *
+ * @param params - The description of the joint to create.
+ * @param parent1 - The first rigid-body attached to this joint.
+ * @param parent2 - The second rigid-body attached to this joint.
+ * @param wakeUp - Should the attached rigid-bodies be awakened?
+ */
+ public createImpulseJoint(
+ params: JointData,
+ parent1: RigidBody,
+ parent2: RigidBody,
+ wakeUp: boolean,
+ ): ImpulseJoint {
+ return this.impulseJoints.createJoint(
+ this.bodies,
+ params,
+ parent1.handle,
+ parent2.handle,
+ wakeUp,
+ );
+ }
+
+ /**
+ * Creates a new multibody joint from the given joint descriptor.
+ *
+ * @param params - The description of the joint to create.
+ * @param parent1 - The first rigid-body attached to this joint.
+ * @param parent2 - The second rigid-body attached to this joint.
+ * @param wakeUp - Should the attached rigid-bodies be awakened?
+ */
+ public createMultibodyJoint(
+ params: JointData,
+ parent1: RigidBody,
+ parent2: RigidBody,
+ wakeUp: boolean,
+ ): MultibodyJoint {
+ return this.multibodyJoints.createJoint(
+ params,
+ parent1.handle,
+ parent2.handle,
+ wakeUp,
+ );
+ }
+
+ /**
+ * Retrieves a rigid-body from its handle.
+ *
+ * @param handle - The integer handle of the rigid-body to retrieve.
+ */
+ public getRigidBody(handle: RigidBodyHandle): RigidBody {
+ return this.bodies.get(handle);
+ }
+
+ /**
+ * Retrieves a collider from its handle.
+ *
+ * @param handle - The integer handle of the collider to retrieve.
+ */
+ public getCollider(handle: ColliderHandle): Collider {
+ return this.colliders.get(handle);
+ }
+
+ /**
+ * Retrieves an impulse joint from its handle.
+ *
+ * @param handle - The integer handle of the impulse joint to retrieve.
+ */
+ public getImpulseJoint(handle: ImpulseJointHandle): ImpulseJoint {
+ return this.impulseJoints.get(handle);
+ }
+
+ /**
+ * Retrieves an multibody joint from its handle.
+ *
+ * @param handle - The integer handle of the multibody joint to retrieve.
+ */
+ public getMultibodyJoint(handle: MultibodyJointHandle): MultibodyJoint {
+ return this.multibodyJoints.get(handle);
+ }
+
+ /**
+ * Removes the given rigid-body from this physics world.
+ *
+ * This will remove this rigid-body as well as all its attached colliders and joints.
+ * Every other bodies touching or attached by joints to this rigid-body will be woken-up.
+ *
+ * @param body - The rigid-body to remove.
+ */
+ public removeRigidBody(body: RigidBody) {
+ if (this.bodies) {
+ this.bodies.remove(
+ body.handle,
+ this.islands,
+ this.colliders,
+ this.impulseJoints,
+ this.multibodyJoints,
+ );
+ }
+ }
+
+ /**
+ * Removes the given collider from this physics world.
+ *
+ * @param collider - The collider to remove.
+ * @param wakeUp - If set to `true`, the rigid-body this collider is attached to will be awaken.
+ */
+ public removeCollider(collider: Collider, wakeUp: boolean) {
+ if (this.colliders) {
+ this.colliders.remove(
+ collider.handle,
+ this.islands,
+ this.bodies,
+ wakeUp,
+ );
+ }
+ }
+
+ /**
+ * Removes the given impulse joint from this physics world.
+ *
+ * @param joint - The impulse joint to remove.
+ * @param wakeUp - If set to `true`, the rigid-bodies attached by this joint will be awaken.
+ */
+ public removeImpulseJoint(joint: ImpulseJoint, wakeUp: boolean) {
+ if (this.impulseJoints) {
+ this.impulseJoints.remove(joint.handle, wakeUp);
+ }
+ }
+
+ /**
+ * Removes the given multibody joint from this physics world.
+ *
+ * @param joint - The multibody joint to remove.
+ * @param wakeUp - If set to `true`, the rigid-bodies attached by this joint will be awaken.
+ */
+ public removeMultibodyJoint(joint: MultibodyJoint, wakeUp: boolean) {
+ if (this.impulseJoints) {
+ this.multibodyJoints.remove(joint.handle, wakeUp);
+ }
+ }
+
+ /**
+ * Applies the given closure to each collider managed by this physics world.
+ *
+ * @param f(collider) - The function to apply to each collider managed by this physics world. Called as `f(collider)`.
+ */
+ public forEachCollider(f: (collider: Collider) => void) {
+ this.colliders.forEach(f);
+ }
+
+ /**
+ * Applies the given closure to each rigid-body managed by this physics world.
+ *
+ * @param f(body) - The function to apply to each rigid-body managed by this physics world. Called as `f(collider)`.
+ */
+ public forEachRigidBody(f: (body: RigidBody) => void) {
+ this.bodies.forEach(f);
+ }
+
+ /**
+ * Applies the given closure to each active rigid-body managed by this physics world.
+ *
+ * After a short time of inactivity, a rigid-body is automatically deactivated ("asleep") by
+ * the physics engine in order to save computational power. A sleeping rigid-body never moves
+ * unless it is moved manually by the user.
+ *
+ * @param f - The function to apply to each active rigid-body managed by this physics world. Called as `f(collider)`.
+ */
+ public forEachActiveRigidBody(f: (body: RigidBody) => void) {
+ this.bodies.forEachActiveRigidBody(this.islands, f);
+ }
+
+ /**
+ * Find the closest intersection between a ray and the physics world.
+ *
+ * @param ray - The ray to cast.
+ * @param maxToi - The maximum time-of-impact that can be reported by this cast. This effectively
+ * limits the length of the ray to `ray.dir.norm() * maxToi`.
+ * @param solid - If `false` then the ray will attempt to hit the boundary of a shape, even if its
+ * origin already lies inside of a shape. In other terms, `true` implies that all shapes are plain,
+ * whereas `false` implies that all shapes are hollow for this ray-cast.
+ * @param groups - Used to filter the colliders that can or cannot be hit by the ray.
+ * @param filter - The callback to filter out which collider will be hit.
+ */
+ public castRay(
+ ray: Ray,
+ maxToi: number,
+ solid: boolean,
+ filterFlags?: QueryFilterFlags,
+ filterGroups?: InteractionGroups,
+ filterExcludeCollider?: Collider,
+ filterExcludeRigidBody?: RigidBody,
+ filterPredicate?: (collider: Collider) => boolean,
+ ): RayColliderHit | null {
+ return this.broadPhase.castRay(
+ this.narrowPhase,
+ this.bodies,
+ this.colliders,
+ ray,
+ maxToi,
+ solid,
+ filterFlags,
+ filterGroups,
+ filterExcludeCollider ? filterExcludeCollider.handle : null,
+ filterExcludeRigidBody ? filterExcludeRigidBody.handle : null,
+ this.colliders.castClosure(filterPredicate),
+ );
+ }
+
+ /**
+ * Find the closest intersection between a ray and the physics world.
+ *
+ * This also computes the normal at the hit point.
+ * @param ray - The ray to cast.
+ * @param maxToi - The maximum time-of-impact that can be reported by this cast. This effectively
+ * limits the length of the ray to `ray.dir.norm() * maxToi`.
+ * @param solid - If `false` then the ray will attempt to hit the boundary of a shape, even if its
+ * origin already lies inside of a shape. In other terms, `true` implies that all shapes are plain,
+ * whereas `false` implies that all shapes are hollow for this ray-cast.
+ * @param groups - Used to filter the colliders that can or cannot be hit by the ray.
+ */
+ public castRayAndGetNormal(
+ ray: Ray,
+ maxToi: number,
+ solid: boolean,
+ filterFlags?: QueryFilterFlags,
+ filterGroups?: InteractionGroups,
+ filterExcludeCollider?: Collider,
+ filterExcludeRigidBody?: RigidBody,
+ filterPredicate?: (collider: Collider) => boolean,
+ ): RayColliderIntersection | null {
+ return this.broadPhase.castRayAndGetNormal(
+ this.narrowPhase,
+ this.bodies,
+ this.colliders,
+ ray,
+ maxToi,
+ solid,
+ filterFlags,
+ filterGroups,
+ filterExcludeCollider ? filterExcludeCollider.handle : null,
+ filterExcludeRigidBody ? filterExcludeRigidBody.handle : null,
+ this.colliders.castClosure(filterPredicate),
+ );
+ }
+
+ /**
+ * Cast a ray and collects all the intersections between a ray and the scene.
+ *
+ * @param ray - The ray to cast.
+ * @param maxToi - The maximum time-of-impact that can be reported by this cast. This effectively
+ * limits the length of the ray to `ray.dir.norm() * maxToi`.
+ * @param solid - If `false` then the ray will attempt to hit the boundary of a shape, even if its
+ * origin already lies inside of a shape. In other terms, `true` implies that all shapes are plain,
+ * whereas `false` implies that all shapes are hollow for this ray-cast.
+ * @param groups - Used to filter the colliders that can or cannot be hit by the ray.
+ * @param callback - The callback called once per hit (in no particular order) between a ray and a collider.
+ * If this callback returns `false`, then the cast will stop and no further hits will be detected/reported.
+ */
+ public intersectionsWithRay(
+ ray: Ray,
+ maxToi: number,
+ solid: boolean,
+ callback: (intersect: RayColliderIntersection) => boolean,
+ filterFlags?: QueryFilterFlags,
+ filterGroups?: InteractionGroups,
+ filterExcludeCollider?: Collider,
+ filterExcludeRigidBody?: RigidBody,
+ filterPredicate?: (collider: Collider) => boolean,
+ ) {
+ this.broadPhase.intersectionsWithRay(
+ this.narrowPhase,
+ this.bodies,
+ this.colliders,
+ ray,
+ maxToi,
+ solid,
+ callback,
+ filterFlags,
+ filterGroups,
+ filterExcludeCollider ? filterExcludeCollider.handle : null,
+ filterExcludeRigidBody ? filterExcludeRigidBody.handle : null,
+ this.colliders.castClosure(filterPredicate),
+ );
+ }
+
+ /**
+ * Gets the handle of up to one collider intersecting the given shape.
+ *
+ * @param shapePos - The position of the shape used for the intersection test.
+ * @param shapeRot - The orientation of the shape used for the intersection test.
+ * @param shape - The shape used for the intersection test.
+ * @param groups - The bit groups and filter associated to the ray, in order to only
+ * hit the colliders with collision groups compatible with the ray's group.
+ */
+ public intersectionWithShape(
+ shapePos: Vector,
+ shapeRot: Rotation,
+ shape: Shape,
+ filterFlags?: QueryFilterFlags,
+ filterGroups?: InteractionGroups,
+ filterExcludeCollider?: Collider,
+ filterExcludeRigidBody?: RigidBody,
+ filterPredicate?: (collider: Collider) => boolean,
+ ): Collider | null {
+ let handle = this.broadPhase.intersectionWithShape(
+ this.narrowPhase,
+ this.bodies,
+ this.colliders,
+ shapePos,
+ shapeRot,
+ shape,
+ filterFlags,
+ filterGroups,
+ filterExcludeCollider ? filterExcludeCollider.handle : null,
+ filterExcludeRigidBody ? filterExcludeRigidBody.handle : null,
+ this.colliders.castClosure(filterPredicate),
+ );
+ return handle != null ? this.colliders.get(handle) : null;
+ }
+
+ /**
+ * Find the projection of a point on the closest collider.
+ *
+ * @param point - The point to project.
+ * @param solid - If this is set to `true` then the collider shapes are considered to
+ * be plain (if the point is located inside of a plain shape, its projection is the point
+ * itself). If it is set to `false` the collider shapes are considered to be hollow
+ * (if the point is located inside of an hollow shape, it is projected on the shape's
+ * boundary).
+ * @param groups - The bit groups and filter associated to the point to project, in order to only
+ * project on colliders with collision groups compatible with the ray's group.
+ */
+ public projectPoint(
+ point: Vector,
+ solid: boolean,
+ filterFlags?: QueryFilterFlags,
+ filterGroups?: InteractionGroups,
+ filterExcludeCollider?: Collider,
+ filterExcludeRigidBody?: RigidBody,
+ filterPredicate?: (collider: Collider) => boolean,
+ ): PointColliderProjection | null {
+ return this.broadPhase.projectPoint(
+ this.narrowPhase,
+ this.bodies,
+ this.colliders,
+ point,
+ solid,
+ filterFlags,
+ filterGroups,
+ filterExcludeCollider ? filterExcludeCollider.handle : null,
+ filterExcludeRigidBody ? filterExcludeRigidBody.handle : null,
+ this.colliders.castClosure(filterPredicate),
+ );
+ }
+
+ /**
+ * Find the projection of a point on the closest collider.
+ *
+ * @param point - The point to project.
+ * @param groups - The bit groups and filter associated to the point to project, in order to only
+ * project on colliders with collision groups compatible with the ray's group.
+ */
+ public projectPointAndGetFeature(
+ point: Vector,
+ filterFlags?: QueryFilterFlags,
+ filterGroups?: InteractionGroups,
+ filterExcludeCollider?: Collider,
+ filterExcludeRigidBody?: RigidBody,
+ filterPredicate?: (collider: Collider) => boolean,
+ ): PointColliderProjection | null {
+ return this.broadPhase.projectPointAndGetFeature(
+ this.narrowPhase,
+ this.bodies,
+ this.colliders,
+ point,
+ filterFlags,
+ filterGroups,
+ filterExcludeCollider ? filterExcludeCollider.handle : null,
+ filterExcludeRigidBody ? filterExcludeRigidBody.handle : null,
+ this.colliders.castClosure(filterPredicate),
+ );
+ }
+
+ /**
+ * Find all the colliders containing the given point.
+ *
+ * @param point - The point used for the containment test.
+ * @param groups - The bit groups and filter associated to the point to test, in order to only
+ * test on colliders with collision groups compatible with the ray's group.
+ * @param callback - A function called with the handles of each collider with a shape
+ * containing the `point`.
+ */
+ public intersectionsWithPoint(
+ point: Vector,
+ callback: (handle: Collider) => boolean,
+ filterFlags?: QueryFilterFlags,
+ filterGroups?: InteractionGroups,
+ filterExcludeCollider?: Collider,
+ filterExcludeRigidBody?: RigidBody,
+ filterPredicate?: (collider: Collider) => boolean,
+ ) {
+ this.broadPhase.intersectionsWithPoint(
+ this.narrowPhase,
+ this.bodies,
+ this.colliders,
+ point,
+ this.colliders.castClosure(callback),
+ filterFlags,
+ filterGroups,
+ filterExcludeCollider ? filterExcludeCollider.handle : null,
+ filterExcludeRigidBody ? filterExcludeRigidBody.handle : null,
+ this.colliders.castClosure(filterPredicate),
+ );
+ }
+
+ /**
+ * Casts a shape at a constant linear velocity and retrieve the first collider it hits.
+ * This is similar to ray-casting except that we are casting a whole shape instead of
+ * just a point (the ray origin).
+ *
+ * @param shapePos - The initial position of the shape to cast.
+ * @param shapeRot - The initial rotation of the shape to cast.
+ * @param shapeVel - The constant velocity of the shape to cast (i.e. the cast direction).
+ * @param shape - The shape to cast.
+ * @param targetDistance − If the shape moves closer to this distance from a collider, a hit
+ * will be returned.
+ * @param maxToi - The maximum time-of-impact that can be reported by this cast. This effectively
+ * limits the distance traveled by the shape to `shapeVel.norm() * maxToi`.
+ * @param stopAtPenetration - If set to `false`, the linear shape-cast won’t immediately stop if
+ * the shape is penetrating another shape at its starting point **and** its trajectory is such
+ * that it’s on a path to exit that penetration state.
+ * @param groups - The bit groups and filter associated to the shape to cast, in order to only
+ * test on colliders with collision groups compatible with this group.
+ */
+ public castShape(
+ shapePos: Vector,
+ shapeRot: Rotation,
+ shapeVel: Vector,
+ shape: Shape,
+ targetDistance: number,
+ maxToi: number,
+ stopAtPenetration: boolean,
+ filterFlags?: QueryFilterFlags,
+ filterGroups?: InteractionGroups,
+ filterExcludeCollider?: Collider,
+ filterExcludeRigidBody?: RigidBody,
+ filterPredicate?: (collider: Collider) => boolean,
+ ): ColliderShapeCastHit | null {
+ return this.broadPhase.castShape(
+ this.narrowPhase,
+ this.bodies,
+ this.colliders,
+ shapePos,
+ shapeRot,
+ shapeVel,
+ shape,
+ targetDistance,
+ maxToi,
+ stopAtPenetration,
+ filterFlags,
+ filterGroups,
+ filterExcludeCollider ? filterExcludeCollider.handle : null,
+ filterExcludeRigidBody ? filterExcludeRigidBody.handle : null,
+ this.colliders.castClosure(filterPredicate),
+ );
+ }
+
+ /**
+ * Retrieve all the colliders intersecting the given shape.
+ *
+ * @param shapePos - The position of the shape to test.
+ * @param shapeRot - The orientation of the shape to test.
+ * @param shape - The shape to test.
+ * @param groups - The bit groups and filter associated to the shape to test, in order to only
+ * test on colliders with collision groups compatible with this group.
+ * @param callback - A function called with the handles of each collider intersecting the `shape`.
+ */
+ public intersectionsWithShape(
+ shapePos: Vector,
+ shapeRot: Rotation,
+ shape: Shape,
+ callback: (collider: Collider) => boolean,
+ filterFlags?: QueryFilterFlags,
+ filterGroups?: InteractionGroups,
+ filterExcludeCollider?: Collider,
+ filterExcludeRigidBody?: RigidBody,
+ filterPredicate?: (collider: Collider) => boolean,
+ ) {
+ this.broadPhase.intersectionsWithShape(
+ this.narrowPhase,
+ this.bodies,
+ this.colliders,
+ shapePos,
+ shapeRot,
+ shape,
+ this.colliders.castClosure(callback),
+ filterFlags,
+ filterGroups,
+ filterExcludeCollider ? filterExcludeCollider.handle : null,
+ filterExcludeRigidBody ? filterExcludeRigidBody.handle : null,
+ this.colliders.castClosure(filterPredicate),
+ );
+ }
+
+ /**
+ * Finds the handles of all the colliders with an AABB intersecting the given AABB.
+ *
+ * @param aabbCenter - The center of the AABB to test.
+ * @param aabbHalfExtents - The half-extents of the AABB to test.
+ * @param callback - The callback that will be called with the handles of all the colliders
+ * currently intersecting the given AABB.
+ */
+ public collidersWithAabbIntersectingAabb(
+ aabbCenter: Vector,
+ aabbHalfExtents: Vector,
+ callback: (handle: Collider) => boolean,
+ ) {
+ this.broadPhase.collidersWithAabbIntersectingAabb(
+ this.narrowPhase,
+ this.bodies,
+ this.colliders,
+ aabbCenter,
+ aabbHalfExtents,
+ this.colliders.castClosure(callback),
+ );
+ }
+
+ /**
+ * Enumerates all the colliders potentially in contact with the given collider.
+ *
+ * @param collider1 - The second collider involved in the contact.
+ * @param f - Closure that will be called on each collider that is in contact with `collider1`.
+ */
+ public contactPairsWith(
+ collider1: Collider,
+ f: (collider2: Collider) => void,
+ ) {
+ this.narrowPhase.contactPairsWith(
+ collider1.handle,
+ this.colliders.castClosure(f),
+ );
+ }
+
+ /**
+ * Enumerates all the colliders intersecting the given colliders, assuming one of them
+ * is a sensor.
+ */
+ public intersectionPairsWith(
+ collider1: Collider,
+ f: (collider2: Collider) => void,
+ ) {
+ this.narrowPhase.intersectionPairsWith(
+ collider1.handle,
+ this.colliders.castClosure(f),
+ );
+ }
+
+ /**
+ * Iterates through all the contact manifolds between the given pair of colliders.
+ *
+ * @param collider1 - The first collider involved in the contact.
+ * @param collider2 - The second collider involved in the contact.
+ * @param f - Closure that will be called on each contact manifold between the two colliders. If the second argument
+ * passed to this closure is `true`, then the contact manifold data is flipped, i.e., methods like `localNormal1`
+ * actually apply to the `collider2` and fields like `localNormal2` apply to the `collider1`.
+ */
+ public contactPair(
+ collider1: Collider,
+ collider2: Collider,
+ f: (manifold: TempContactManifold, flipped: boolean) => void,
+ ) {
+ this.narrowPhase.contactPair(collider1.handle, collider2.handle, f);
+ }
+
+ /**
+ * Returns `true` if `collider1` and `collider2` intersect and at least one of them is a sensor.
+ * @param collider1 − The first collider involved in the intersection.
+ * @param collider2 − The second collider involved in the intersection.
+ */
+ public intersectionPair(collider1: Collider, collider2: Collider): boolean {
+ return this.narrowPhase.intersectionPair(
+ collider1.handle,
+ collider2.handle,
+ );
+ }
+
+ /**
+ * Sets whether internal performance profiling is enabled (default: false).
+ *
+ * Only works if the internal profiler is enabled with `World.profilerEnabled = true`.
+ */
+ set profilerEnabled(enabled: boolean) {
+ this.physicsPipeline.raw.set_profiler_enabled(enabled);
+ }
+
+ /**
+ * Indicates if the internal performance profiling is enabled.
+ *
+ * Only works if the internal profiler is enabled with `World.profilerEnabled = true`.
+ */
+ get profilerEnabled(): boolean {
+ return this.physicsPipeline.raw.is_profiler_enabled();
+ }
+
+ /**
+ * The time spent in milliseconds by the last step to run the entire simulation step.
+ *
+ * Only works if the internal profiler is enabled with `World.profilerEnabled = true`.
+ */
+ public timingStep(): number {
+ return this.physicsPipeline.raw.timing_step();
+ }
+
+ /**
+ * The time spent in milliseconds by the last step to run the collision-detection
+ * (broad-phase + narrow-phase).
+ *
+ * Only works if the internal profiler is enabled with `World.profilerEnabled = true`.
+ */
+ public timingCollisionDetection(): number {
+ return this.physicsPipeline.raw.timing_collision_detection();
+ }
+
+ /**
+ * The time spent in milliseconds by the last step to run the broad-phase.
+ *
+ * This timing is included in `timingCollisionDetection`.
+ * Only works if the internal profiler is enabled with `World.profilerEnabled = true`.
+ */
+ public timingBroadPhase(): number {
+ return this.physicsPipeline.raw.timing_broad_phase();
+ }
+
+ /**
+ * The time spent in milliseconds by the last step to run the narrow-phase.
+ *
+ * This timing is included in `timingCollisionDetection`.
+ * Only works if the internal profiler is enabled with `World.profilerEnabled = true`.
+ */
+ public timingNarrowPhase(): number {
+ return this.physicsPipeline.raw.timing_narrow_phase();
+ }
+
+ /**
+ * The time spent in milliseconds by the last step to run the constraint solver.
+ *
+ * Only works if the internal profiler is enabled with `World.profilerEnabled = true`.
+ */
+ public timingSolver(): number {
+ return this.physicsPipeline.raw.timing_solver();
+ }
+
+ /**
+ * The time spent in milliseconds by the last step to run the constraint
+ * initialization.
+ *
+ * This timing is included in `timingSolver`.
+ * Only works if the internal profiler is enabled with `World.profilerEnabled = true`.
+ */
+ public timingVelocityAssembly(): number {
+ return this.physicsPipeline.raw.timing_velocity_assembly();
+ }
+
+ /**
+ * The time spent in milliseconds by the last step to run the constraint
+ * resolution.
+ *
+ * This timing is included in `timingSolver`.
+ * Only works if the internal profiler is enabled with `World.profilerEnabled = true`.
+ */
+ public timingVelocityResolution(): number {
+ return this.physicsPipeline.raw.timing_velocity_resolution();
+ }
+
+ /**
+ * The time spent in milliseconds by the last step to run the rigid-body
+ * velocity update.
+ *
+ * This timing is included in `timingSolver`.
+ * Only works if the internal profiler is enabled with `World.profilerEnabled = true`.
+ */
+ public timingVelocityUpdate(): number {
+ return this.physicsPipeline.raw.timing_velocity_update();
+ }
+
+ /**
+ * The time spent in milliseconds by writing rigid-body velocities
+ * calculated by the solver back into the rigid-bodies.
+ *
+ * This timing is included in `timingSolver`.
+ * Only works if the internal profiler is enabled with `World.profilerEnabled = true`.
+ */
+ public timingVelocityWriteback(): number {
+ return this.physicsPipeline.raw.timing_velocity_writeback();
+ }
+
+ /**
+ * The total time spent in CCD detection and resolution.
+ *
+ * Only works if the internal profiler is enabled with `World.profilerEnabled = true`.
+ */
+ public timingCcd(): number {
+ return this.physicsPipeline.raw.timing_ccd();
+ }
+
+ /**
+ * The total time spent searching for the continuous hits during CCD.
+ *
+ * This timing is included in `timingCcd`.
+ * Only works if the internal profiler is enabled with `World.profilerEnabled = true`.
+ */
+ public timingCcdToiComputation(): number {
+ return this.physicsPipeline.raw.timing_ccd_toi_computation();
+ }
+
+ /**
+ * The total time spent in the broad-phase during CCD.
+ *
+ * This timing is included in `timingCcd`.
+ * Only works if the internal profiler is enabled with `World.profilerEnabled = true`.
+ */
+ public timingCcdBroadPhase(): number {
+ return this.physicsPipeline.raw.timing_ccd_broad_phase();
+ }
+
+ /**
+ * The total time spent in the narrow-phase during CCD.
+ *
+ * This timing is included in `timingCcd`.
+ * Only works if the internal profiler is enabled with `World.profilerEnabled = true`.
+ */
+ public timingCcdNarrowPhase(): number {
+ return this.physicsPipeline.raw.timing_ccd_narrow_phase();
+ }
+
+ /**
+ * The total time spent in the constraints resolution during CCD.
+ *
+ * This timing is included in `timingCcd`.
+ * Only works if the internal profiler is enabled with `World.profilerEnabled = true`.
+ */
+ public timingCcdSolver(): number {
+ return this.physicsPipeline.raw.timing_ccd_solver();
+ }
+
+ /**
+ * The total time spent in the islands calculation during CCD.
+ *
+ * Only works if the internal profiler is enabled with `World.profilerEnabled = true`.
+ */
+ public timingIslandConstruction(): number {
+ return this.physicsPipeline.raw.timing_island_construction();
+ }
+
+ /**
+ * The total time spent propagating detected user changes.
+ *
+ * Only works if the internal profiler is enabled with `World.profilerEnabled = true`.
+ */
+ public timingUserChanges(): number {
+ return this.physicsPipeline.raw.timing_user_changes();
+ }
+}
diff --git a/typescript/src.ts/rapier.ts b/typescript/src.ts/rapier.ts
new file mode 100644
index 000000000..dbf4d053a
--- /dev/null
+++ b/typescript/src.ts/rapier.ts
@@ -0,0 +1,3 @@
+import * as RAPIER from "./exports";
+export * from "./exports";
+export default RAPIER;
diff --git a/typescript/src.ts/raw.ts b/typescript/src.ts/raw.ts
new file mode 100644
index 000000000..51f837b78
--- /dev/null
+++ b/typescript/src.ts/raw.ts
@@ -0,0 +1 @@
+export * from "../rapier3d/pkg/rapier_wasm3d";
diff --git a/typescript/src/control/character_controller.rs b/typescript/src/control/character_controller.rs
new file mode 100644
index 000000000..8456624ea
--- /dev/null
+++ b/typescript/src/control/character_controller.rs
@@ -0,0 +1,366 @@
+use crate::dynamics::RawRigidBodySet;
+use crate::geometry::{RawBroadPhase, RawColliderSet, RawNarrowPhase};
+use crate::math::RawVector;
+use crate::utils::{self, FlatHandle};
+use rapier::control::{
+ CharacterAutostep, CharacterCollision, CharacterLength, EffectiveCharacterMovement,
+ KinematicCharacterController,
+};
+use rapier::geometry::{ColliderHandle, ShapeCastHit};
+use rapier::math::{Pose, Real, Vector};
+use rapier::parry::query::ShapeCastStatus;
+use rapier::pipeline::{QueryFilter, QueryFilterFlags};
+use wasm_bindgen::prelude::*;
+
+#[wasm_bindgen]
+pub struct RawKinematicCharacterController {
+ controller: KinematicCharacterController,
+ result: EffectiveCharacterMovement,
+ events: Vec,
+}
+
+fn length_value(length: CharacterLength) -> Real {
+ match length {
+ CharacterLength::Absolute(val) => val,
+ CharacterLength::Relative(val) => val,
+ }
+}
+#[wasm_bindgen]
+impl RawKinematicCharacterController {
+ #[wasm_bindgen(constructor)]
+ pub fn new(offset: Real) -> Self {
+ let controller = KinematicCharacterController {
+ offset: CharacterLength::Absolute(offset),
+ autostep: None,
+ snap_to_ground: None,
+ ..KinematicCharacterController::default()
+ };
+
+ Self {
+ controller,
+ result: EffectiveCharacterMovement {
+ translation: Vector::ZERO,
+ grounded: false,
+ is_sliding_down_slope: false,
+ },
+ events: vec![],
+ }
+ }
+
+ pub fn up(&self) -> RawVector {
+ self.controller.up.into()
+ }
+
+ pub fn setUp(&mut self, vector: &RawVector) {
+ self.controller.up = vector.0.normalize();
+ }
+
+ pub fn normalNudgeFactor(&self) -> Real {
+ self.controller.normal_nudge_factor
+ }
+
+ pub fn setNormalNudgeFactor(&mut self, value: Real) {
+ self.controller.normal_nudge_factor = value;
+ }
+
+ pub fn offset(&self) -> Real {
+ length_value(self.controller.offset)
+ }
+
+ pub fn setOffset(&mut self, value: Real) {
+ self.controller.offset = CharacterLength::Absolute(value);
+ }
+
+ pub fn slideEnabled(&self) -> bool {
+ self.controller.slide
+ }
+
+ pub fn setSlideEnabled(&mut self, enabled: bool) {
+ self.controller.slide = enabled
+ }
+
+ pub fn autostepMaxHeight(&self) -> Option {
+ self.controller.autostep.map(|e| length_value(e.max_height))
+ }
+
+ pub fn autostepMinWidth(&self) -> Option {
+ self.controller.autostep.map(|e| length_value(e.min_width))
+ }
+
+ pub fn autostepIncludesDynamicBodies(&self) -> Option {
+ self.controller.autostep.map(|e| e.include_dynamic_bodies)
+ }
+
+ pub fn autostepEnabled(&self) -> bool {
+ self.controller.autostep.is_some()
+ }
+
+ pub fn enableAutostep(&mut self, maxHeight: Real, minWidth: Real, includeDynamicBodies: bool) {
+ self.controller.autostep = Some(CharacterAutostep {
+ min_width: CharacterLength::Absolute(minWidth),
+ max_height: CharacterLength::Absolute(maxHeight),
+ include_dynamic_bodies: includeDynamicBodies,
+ })
+ }
+
+ pub fn disableAutostep(&mut self) {
+ self.controller.autostep = None;
+ }
+
+ pub fn maxSlopeClimbAngle(&self) -> Real {
+ self.controller.max_slope_climb_angle
+ }
+
+ pub fn setMaxSlopeClimbAngle(&mut self, angle: Real) {
+ self.controller.max_slope_climb_angle = angle;
+ }
+
+ pub fn minSlopeSlideAngle(&self) -> Real {
+ self.controller.min_slope_slide_angle
+ }
+
+ pub fn setMinSlopeSlideAngle(&mut self, angle: Real) {
+ self.controller.min_slope_slide_angle = angle
+ }
+
+ pub fn snapToGroundDistance(&self) -> Option {
+ self.controller.snap_to_ground.map(length_value)
+ }
+
+ pub fn enableSnapToGround(&mut self, distance: Real) {
+ self.controller.snap_to_ground = Some(CharacterLength::Absolute(distance));
+ }
+
+ pub fn disableSnapToGround(&mut self) {
+ self.controller.snap_to_ground = None;
+ }
+
+ pub fn snapToGroundEnabled(&self) -> bool {
+ self.controller.snap_to_ground.is_some()
+ }
+
+ pub fn computeColliderMovement(
+ &mut self,
+ dt: Real,
+ broad_phase: &RawBroadPhase,
+ narrow_phase: &RawNarrowPhase,
+ bodies: &mut RawRigidBodySet,
+ colliders: &mut RawColliderSet,
+ collider_handle: FlatHandle,
+ desired_translation_delta: &RawVector,
+ apply_impulses_to_dynamic_bodies: bool,
+ character_mass: Option,
+ filter_flags: u32,
+ filter_groups: Option,
+ filter_predicate: &js_sys::Function,
+ ) {
+ let handle = crate::utils::collider_handle(collider_handle);
+ if let Some(collider) = colliders.0.get(handle) {
+ let collider_pose = *collider.position();
+ let collider_shape = collider.shared_shape().clone();
+ let collider_parent = collider.parent();
+
+ crate::utils::with_filter(filter_predicate, |predicate| {
+ let query_filter = QueryFilter {
+ flags: QueryFilterFlags::from_bits(filter_flags)
+ .unwrap_or(QueryFilterFlags::empty()),
+ groups: filter_groups.map(crate::geometry::unpack_interaction_groups),
+ exclude_collider: Some(handle),
+ exclude_rigid_body: collider_parent,
+ predicate,
+ };
+
+ let character_mass = character_mass
+ .or_else(|| {
+ collider_parent
+ .and_then(|h| bodies.0.get(h))
+ .map(|b| b.mass())
+ })
+ .unwrap_or(0.0);
+
+ let mut query_pipeline = broad_phase.0.as_query_pipeline_mut(
+ narrow_phase.0.query_dispatcher(),
+ &mut bodies.0,
+ &mut colliders.0,
+ query_filter,
+ );
+
+ self.events.clear();
+ let events = &mut self.events;
+ self.result = self.controller.move_shape(
+ dt,
+ &query_pipeline.as_ref(),
+ &*collider_shape,
+ &collider_pose,
+ desired_translation_delta.0,
+ |event| events.push(event),
+ );
+
+ if apply_impulses_to_dynamic_bodies {
+ self.controller.solve_character_collision_impulses(
+ dt,
+ &mut query_pipeline,
+ &*collider_shape,
+ character_mass,
+ self.events.iter(),
+ );
+ }
+ });
+ } else {
+ self.result.translation = Vector::ZERO;
+ }
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn computedMovement(&self, scratch_buffer: &js_sys::Float32Array) {
+ let u = self.result.translation;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn computedMovement(&self, scratch_buffer: &js_sys::Float32Array) {
+ let u = self.result.translation;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ }
+
+ pub fn computedGrounded(&self) -> bool {
+ self.result.grounded
+ }
+
+ pub fn numComputedCollisions(&self) -> usize {
+ self.events.len()
+ }
+
+ pub fn computedCollision(&self, i: usize, collision: &mut RawCharacterCollision) -> bool {
+ if let Some(coll) = self.events.get(i) {
+ collision.0 = *coll;
+ }
+
+ i < self.events.len()
+ }
+}
+
+#[wasm_bindgen]
+pub struct RawCharacterCollision(CharacterCollision);
+
+#[wasm_bindgen]
+impl RawCharacterCollision {
+ #[wasm_bindgen(constructor)]
+ pub fn new() -> Self {
+ Self(CharacterCollision {
+ handle: ColliderHandle::invalid(),
+ character_pos: Pose::identity(),
+ translation_applied: Vector::ZERO,
+ translation_remaining: Vector::ZERO,
+ hit: ShapeCastHit {
+ time_of_impact: 0.0,
+ witness1: Vector::ZERO,
+ witness2: Vector::ZERO,
+ normal1: Vector::Y,
+ normal2: Vector::Y,
+ status: ShapeCastStatus::Failed,
+ },
+ })
+ }
+
+ pub fn handle(&self) -> FlatHandle {
+ utils::flat_handle(self.0.handle.0)
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn translationDeltaApplied(&self, scratch_buffer: &js_sys::Float32Array) {
+ let u = self.0.translation_applied;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn translationDeltaApplied(&self, scratch_buffer: &js_sys::Float32Array) {
+ let u = self.0.translation_applied;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn translationDeltaRemaining(&self, scratch_buffer: &js_sys::Float32Array) {
+ let u = self.0.translation_remaining;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn translationDeltaRemaining(&self, scratch_buffer: &js_sys::Float32Array) {
+ let u = self.0.translation_remaining;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ }
+
+ pub fn toi(&self) -> Real {
+ self.0.hit.time_of_impact
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn worldWitness1(&self, scratch_buffer: &js_sys::Float32Array) {
+ let u = self.0.hit.witness1; // Already in world-space.
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn worldWitness1(&self, scratch_buffer: &js_sys::Float32Array) {
+ let u = self.0.hit.witness1; // Already in world-space.
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn worldWitness2(&self, scratch_buffer: &js_sys::Float32Array) {
+ let u = self.0.character_pos.transform_point(self.0.hit.witness2);
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn worldWitness2(&self, scratch_buffer: &js_sys::Float32Array) {
+ let u = self.0.character_pos.transform_point(self.0.hit.witness2);
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn worldNormal1(&self, scratch_buffer: &js_sys::Float32Array) {
+ let u = self.0.hit.normal1; // Already in world-space.
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn worldNormal1(&self, scratch_buffer: &js_sys::Float32Array) {
+ let u = self.0.hit.normal1; // Already in world-space.
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn worldNormal2(&self, scratch_buffer: &js_sys::Float32Array) {
+ let u = self.0.character_pos.transform_vector(self.0.hit.normal2);
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn worldNormal2(&self, scratch_buffer: &js_sys::Float32Array) {
+ let u = self.0.character_pos.transform_vector(self.0.hit.normal2);
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ }
+}
diff --git a/typescript/src/control/mod.rs b/typescript/src/control/mod.rs
new file mode 100644
index 000000000..74352c2ba
--- /dev/null
+++ b/typescript/src/control/mod.rs
@@ -0,0 +1,11 @@
+pub use self::character_controller::RawKinematicCharacterController;
+pub use self::pid_controller::RawPidController;
+
+#[cfg(feature = "dim3")]
+pub use self::ray_cast_vehicle_controller::RawDynamicRayCastVehicleController;
+
+mod character_controller;
+mod pid_controller;
+
+#[cfg(feature = "dim3")]
+mod ray_cast_vehicle_controller;
diff --git a/typescript/src/control/pid_controller.rs b/typescript/src/control/pid_controller.rs
new file mode 100644
index 000000000..a29eb684f
--- /dev/null
+++ b/typescript/src/control/pid_controller.rs
@@ -0,0 +1,286 @@
+use crate::dynamics::RawRigidBodySet;
+use crate::math::RawVector;
+use crate::utils::{self, FlatHandle};
+use rapier::control::PidController;
+use rapier::dynamics::AxesMask;
+use rapier::math::Vector;
+use wasm_bindgen::prelude::*;
+
+#[cfg(feature = "dim3")]
+use crate::math::RawRotation;
+#[cfg(feature = "dim2")]
+use rapier::math::Rotation;
+
+#[wasm_bindgen]
+pub struct RawPidController {
+ controller: PidController,
+}
+
+#[wasm_bindgen]
+impl RawPidController {
+ #[wasm_bindgen(constructor)]
+ pub fn new(kp: f32, ki: f32, kd: f32, axes_mask: u8) -> Self {
+ let controller = PidController::new(
+ kp,
+ ki,
+ kd,
+ AxesMask::from_bits(axes_mask).unwrap_or(AxesMask::all()),
+ );
+ Self { controller }
+ }
+
+ pub fn set_kp(&mut self, kp: f32, axes: u8) {
+ let axes = AxesMask::from_bits(axes).unwrap_or(AxesMask::all());
+ if axes.contains(AxesMask::LIN_X) {
+ self.controller.pd.lin_kp.x = kp;
+ }
+ if axes.contains(AxesMask::LIN_Y) {
+ self.controller.pd.lin_kp.y = kp;
+ }
+ #[cfg(feature = "dim3")]
+ if axes.contains(AxesMask::LIN_Z) {
+ self.controller.pd.lin_kp.z = kp;
+ }
+ #[cfg(feature = "dim3")]
+ if axes.contains(AxesMask::ANG_X) {
+ self.controller.pd.ang_kp.x = kp;
+ }
+ #[cfg(feature = "dim3")]
+ if axes.contains(AxesMask::ANG_Y) {
+ self.controller.pd.ang_kp.y = kp;
+ }
+ if axes.contains(AxesMask::ANG_Z) {
+ #[cfg(feature = "dim2")]
+ {
+ self.controller.pd.ang_kp = kp;
+ }
+ #[cfg(feature = "dim3")]
+ {
+ self.controller.pd.ang_kp.z = kp;
+ }
+ }
+ }
+
+ pub fn set_ki(&mut self, ki: f32, axes: u8) {
+ let axes = AxesMask::from_bits(axes).unwrap_or(AxesMask::all());
+ if axes.contains(AxesMask::LIN_X) {
+ self.controller.lin_ki.x = ki;
+ }
+ if axes.contains(AxesMask::LIN_Y) {
+ self.controller.lin_ki.y = ki;
+ }
+ #[cfg(feature = "dim3")]
+ if axes.contains(AxesMask::LIN_Z) {
+ self.controller.lin_ki.z = ki;
+ }
+ #[cfg(feature = "dim3")]
+ if axes.contains(AxesMask::ANG_X) {
+ self.controller.ang_ki.x = ki;
+ }
+ #[cfg(feature = "dim3")]
+ if axes.contains(AxesMask::ANG_Y) {
+ self.controller.ang_ki.y = ki;
+ }
+ if axes.contains(AxesMask::ANG_Z) {
+ #[cfg(feature = "dim2")]
+ {
+ self.controller.ang_ki = ki;
+ }
+ #[cfg(feature = "dim3")]
+ {
+ self.controller.ang_ki.z = ki;
+ }
+ }
+ }
+
+ pub fn set_kd(&mut self, kd: f32, axes: u8) {
+ let axes = AxesMask::from_bits(axes).unwrap_or(AxesMask::all());
+ if axes.contains(AxesMask::LIN_X) {
+ self.controller.pd.lin_kd.x = kd;
+ }
+ if axes.contains(AxesMask::LIN_Y) {
+ self.controller.pd.lin_kd.x = kd;
+ }
+ #[cfg(feature = "dim3")]
+ if axes.contains(AxesMask::LIN_Z) {
+ self.controller.pd.lin_kd.x = kd;
+ }
+ #[cfg(feature = "dim3")]
+ if axes.contains(AxesMask::ANG_X) {
+ self.controller.pd.ang_kd.x = kd;
+ }
+ #[cfg(feature = "dim3")]
+ if axes.contains(AxesMask::ANG_Y) {
+ self.controller.pd.ang_kd.y = kd;
+ }
+ if axes.contains(AxesMask::ANG_Z) {
+ #[cfg(feature = "dim2")]
+ {
+ self.controller.pd.ang_kd = kd;
+ }
+ #[cfg(feature = "dim3")]
+ {
+ self.controller.pd.ang_kd.z = kd;
+ }
+ }
+ }
+
+ pub fn set_axes_mask(&mut self, axes_mask: u8) {
+ if let Some(mask) = AxesMask::from_bits(axes_mask) {
+ self.controller.pd.axes = mask;
+ }
+ }
+
+ pub fn reset_integrals(&mut self) {
+ self.controller.reset_integrals();
+ }
+
+ pub fn apply_linear_correction(
+ &mut self,
+ dt: f32,
+ bodies: &mut RawRigidBodySet,
+ rb_handle: FlatHandle,
+ target_translation: &RawVector,
+ target_linvel: &RawVector,
+ ) {
+ let rb_handle = utils::body_handle(rb_handle);
+ let Some(rb) = bodies.0.get_mut(rb_handle) else {
+ return;
+ };
+
+ let correction = self.controller.linear_rigid_body_correction(
+ dt,
+ rb,
+ target_translation.0.into(),
+ target_linvel.0,
+ );
+ rb.set_linvel(rb.linvel() + correction, true);
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn apply_angular_correction(
+ &mut self,
+ dt: f32,
+ bodies: &mut RawRigidBodySet,
+ rb_handle: FlatHandle,
+ target_rotation: f32,
+ target_angvel: f32,
+ ) {
+ let rb_handle = crate::utils::body_handle(rb_handle);
+ let Some(rb) = bodies.0.get_mut(rb_handle) else {
+ return;
+ };
+
+ let correction = self.controller.angular_rigid_body_correction(
+ dt,
+ rb,
+ Rotation::new(target_rotation),
+ target_angvel,
+ );
+ rb.set_angvel(rb.angvel() + correction, true);
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn apply_angular_correction(
+ &mut self,
+ dt: f32,
+ bodies: &mut RawRigidBodySet,
+ rb_handle: FlatHandle,
+ target_rotation: &RawRotation,
+ target_angvel: &RawVector,
+ ) {
+ let rb_handle = crate::utils::body_handle(rb_handle);
+ let Some(rb) = bodies.0.get_mut(rb_handle) else {
+ return;
+ };
+
+ let correction = self.controller.angular_rigid_body_correction(
+ dt,
+ rb,
+ target_rotation.0,
+ target_angvel.0,
+ );
+ rb.set_angvel(rb.angvel() + correction, true);
+ }
+
+ pub fn linear_correction(
+ &mut self,
+ dt: f32,
+ bodies: &RawRigidBodySet,
+ rb_handle: FlatHandle,
+ target_translation: &RawVector,
+ target_linvel: &RawVector,
+ scratch_buffer: &js_sys::Float32Array,
+ ) {
+ let rb_handle = crate::utils::body_handle(rb_handle);
+ let Some(rb) = bodies.0.get(rb_handle) else {
+ scratch_buffer.set_index(0, 0.0);
+ scratch_buffer.set_index(1, 0.0);
+ #[cfg(feature = "dim3")]
+ scratch_buffer.set_index(2, 0.0);
+ return;
+ };
+
+ let u: Vector = self.controller.linear_rigid_body_correction(
+ dt,
+ rb,
+ target_translation.0.into(),
+ target_linvel.0,
+ );
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ #[cfg(feature = "dim3")]
+ scratch_buffer.set_index(2, u.z);
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn angular_correction(
+ &mut self,
+ dt: f32,
+ bodies: &RawRigidBodySet,
+ rb_handle: FlatHandle,
+ target_rotation: f32,
+ target_angvel: f32,
+ ) -> f32 {
+ let rb_handle = crate::utils::body_handle(rb_handle);
+ let Some(rb) = bodies.0.get(rb_handle) else {
+ return 0.0;
+ };
+
+ self.controller.angular_rigid_body_correction(
+ dt,
+ rb,
+ Rotation::new(target_rotation),
+ target_angvel,
+ )
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn angular_correction(
+ &mut self,
+ dt: f32,
+ bodies: &RawRigidBodySet,
+ rb_handle: FlatHandle,
+ target_rotation: &RawRotation,
+ target_angvel: &RawVector,
+ scratch_buffer: &js_sys::Float32Array,
+ ) {
+ let rb_handle = crate::utils::body_handle(rb_handle);
+ let Some(rb) = bodies.0.get(rb_handle) else {
+ scratch_buffer.set_index(0, 0.0);
+ scratch_buffer.set_index(1, 0.0);
+ scratch_buffer.set_index(2, 0.0);
+ return;
+ };
+
+ let u: Vector = self.controller.angular_rigid_body_correction(
+ dt,
+ rb,
+ target_rotation.0,
+ target_angvel.0,
+ );
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ }
+}
diff --git a/typescript/src/control/ray_cast_vehicle_controller.rs b/typescript/src/control/ray_cast_vehicle_controller.rs
new file mode 100644
index 000000000..445037ceb
--- /dev/null
+++ b/typescript/src/control/ray_cast_vehicle_controller.rs
@@ -0,0 +1,434 @@
+use crate::dynamics::RawRigidBodySet;
+use crate::geometry::{RawBroadPhase, RawColliderSet, RawNarrowPhase};
+use crate::math::RawVector;
+use crate::utils::{self, FlatHandle};
+use rapier::control::{DynamicRayCastVehicleController, WheelTuning};
+use rapier::math::Real;
+use rapier::pipeline::{QueryFilter, QueryFilterFlags};
+use wasm_bindgen::prelude::*;
+
+#[wasm_bindgen]
+pub struct RawDynamicRayCastVehicleController {
+ controller: DynamicRayCastVehicleController,
+}
+
+#[wasm_bindgen]
+impl RawDynamicRayCastVehicleController {
+ #[wasm_bindgen(constructor)]
+ pub fn new(chassis: FlatHandle) -> Self {
+ Self {
+ controller: DynamicRayCastVehicleController::new(utils::body_handle(chassis)),
+ }
+ }
+
+ pub fn current_vehicle_speed(&self) -> Real {
+ self.controller.current_vehicle_speed
+ }
+
+ pub fn chassis(&self) -> FlatHandle {
+ utils::flat_handle(self.controller.chassis.0)
+ }
+
+ pub fn index_up_axis(&self) -> usize {
+ self.controller.index_up_axis
+ }
+ pub fn set_index_up_axis(&mut self, axis: usize) {
+ self.controller.index_up_axis = axis;
+ }
+
+ pub fn index_forward_axis(&self) -> usize {
+ self.controller.index_forward_axis
+ }
+ pub fn set_index_forward_axis(&mut self, axis: usize) {
+ self.controller.index_forward_axis = axis;
+ }
+
+ pub fn add_wheel(
+ &mut self,
+ chassis_connection_cs: &RawVector,
+ direction_cs: &RawVector,
+ axle_cs: &RawVector,
+ suspension_rest_length: Real,
+ radius: Real,
+ ) {
+ self.controller.add_wheel(
+ chassis_connection_cs.0.into(),
+ direction_cs.0,
+ axle_cs.0,
+ suspension_rest_length,
+ radius,
+ &WheelTuning::default(),
+ );
+ }
+
+ pub fn num_wheels(&self) -> usize {
+ self.controller.wheels().len()
+ }
+
+ pub fn update_vehicle(
+ &mut self,
+ dt: Real,
+ broad_phase: &RawBroadPhase,
+ narrow_phase: &RawNarrowPhase,
+ bodies: &mut RawRigidBodySet,
+ colliders: &mut RawColliderSet,
+ filter_flags: u32,
+ filter_groups: Option,
+ filter_predicate: &js_sys::Function,
+ ) {
+ crate::utils::with_filter(filter_predicate, |predicate| {
+ let query_filter = QueryFilter {
+ flags: QueryFilterFlags::from_bits(filter_flags)
+ .unwrap_or(QueryFilterFlags::empty()),
+ groups: filter_groups.map(crate::geometry::unpack_interaction_groups),
+ predicate,
+ exclude_rigid_body: Some(self.controller.chassis),
+ exclude_collider: None,
+ };
+
+ let query_pipeline = broad_phase.0.as_query_pipeline_mut(
+ narrow_phase.0.query_dispatcher(),
+ &mut bodies.0,
+ &mut colliders.0,
+ query_filter,
+ );
+
+ self.controller.update_vehicle(dt, query_pipeline);
+ });
+ }
+
+ /*
+ *
+ * Access to wheel properties.
+ *
+ */
+ /*
+ * Getters + setters
+ */
+ #[cfg(feature = "dim2")]
+ pub fn wheel_chassis_connection_point_cs(
+ &self,
+ i: usize,
+ scratch_buffer: &js_sys::Float32Array,
+ ) -> bool {
+ self.controller.wheels().get(i).map_or(false, |w| {
+ let u = w.chassis_connection_point_cs;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ true
+ })
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn wheel_chassis_connection_point_cs(
+ &self,
+ i: usize,
+ scratch_buffer: &js_sys::Float32Array,
+ ) -> bool {
+ self.controller.wheels().get(i).map_or(false, |w| {
+ let u = w.chassis_connection_point_cs;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ true
+ })
+ }
+
+ pub fn set_wheel_chassis_connection_point_cs(&mut self, i: usize, value: &RawVector) {
+ if let Some(wheel) = self.controller.wheels_mut().get_mut(i) {
+ wheel.chassis_connection_point_cs = value.0.into();
+ }
+ }
+
+ pub fn wheel_suspension_rest_length(&self, i: usize) -> Option {
+ self.controller
+ .wheels()
+ .get(i)
+ .map(|w| w.suspension_rest_length)
+ }
+ pub fn set_wheel_suspension_rest_length(&mut self, i: usize, value: Real) {
+ if let Some(wheel) = self.controller.wheels_mut().get_mut(i) {
+ wheel.suspension_rest_length = value;
+ }
+ }
+
+ pub fn wheel_max_suspension_travel(&self, i: usize) -> Option {
+ self.controller
+ .wheels()
+ .get(i)
+ .map(|w| w.max_suspension_travel)
+ }
+ pub fn set_wheel_max_suspension_travel(&mut self, i: usize, value: Real) {
+ if let Some(wheel) = self.controller.wheels_mut().get_mut(i) {
+ wheel.max_suspension_travel = value;
+ }
+ }
+
+ pub fn wheel_radius(&self, i: usize) -> Option {
+ self.controller.wheels().get(i).map(|w| w.radius)
+ }
+ pub fn set_wheel_radius(&mut self, i: usize, value: Real) {
+ if let Some(wheel) = self.controller.wheels_mut().get_mut(i) {
+ wheel.radius = value;
+ }
+ }
+
+ pub fn wheel_suspension_stiffness(&self, i: usize) -> Option {
+ self.controller
+ .wheels()
+ .get(i)
+ .map(|w| w.suspension_stiffness)
+ }
+ pub fn set_wheel_suspension_stiffness(&mut self, i: usize, value: Real) {
+ if let Some(wheel) = self.controller.wheels_mut().get_mut(i) {
+ wheel.suspension_stiffness = value;
+ }
+ }
+
+ pub fn wheel_suspension_compression(&self, i: usize) -> Option {
+ self.controller
+ .wheels()
+ .get(i)
+ .map(|w| w.damping_compression)
+ }
+ pub fn set_wheel_suspension_compression(&mut self, i: usize, value: Real) {
+ if let Some(wheel) = self.controller.wheels_mut().get_mut(i) {
+ wheel.damping_compression = value;
+ }
+ }
+
+ pub fn wheel_suspension_relaxation(&self, i: usize) -> Option {
+ self.controller
+ .wheels()
+ .get(i)
+ .map(|w| w.damping_relaxation)
+ }
+ pub fn set_wheel_suspension_relaxation(&mut self, i: usize, value: Real) {
+ if let Some(wheel) = self.controller.wheels_mut().get_mut(i) {
+ wheel.damping_relaxation = value;
+ }
+ }
+
+ pub fn wheel_max_suspension_force(&self, i: usize) -> Option {
+ self.controller
+ .wheels()
+ .get(i)
+ .map(|w| w.max_suspension_force)
+ }
+ pub fn set_wheel_max_suspension_force(&mut self, i: usize, value: Real) {
+ if let Some(wheel) = self.controller.wheels_mut().get_mut(i) {
+ wheel.max_suspension_force = value;
+ }
+ }
+
+ pub fn wheel_brake(&self, i: usize) -> Option {
+ self.controller.wheels().get(i).map(|w| w.brake)
+ }
+ pub fn set_wheel_brake(&mut self, i: usize, value: Real) {
+ if let Some(wheel) = self.controller.wheels_mut().get_mut(i) {
+ wheel.brake = value;
+ }
+ }
+
+ pub fn wheel_steering(&self, i: usize) -> Option {
+ self.controller.wheels().get(i).map(|w| w.steering)
+ }
+ pub fn set_wheel_steering(&mut self, i: usize, value: Real) {
+ if let Some(wheel) = self.controller.wheels_mut().get_mut(i) {
+ wheel.steering = value;
+ }
+ }
+
+ pub fn wheel_engine_force(&self, i: usize) -> Option {
+ self.controller.wheels().get(i).map(|w| w.engine_force)
+ }
+ pub fn set_wheel_engine_force(&mut self, i: usize, value: Real) {
+ if let Some(wheel) = self.controller.wheels_mut().get_mut(i) {
+ wheel.engine_force = value;
+ }
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn wheel_direction_cs(&self, i: usize, scratch_buffer: &js_sys::Float32Array) -> bool {
+ self.controller.wheels().get(i).map_or(false, |w| {
+ let u = w.direction_cs;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ true
+ })
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn wheel_direction_cs(&self, i: usize, scratch_buffer: &js_sys::Float32Array) -> bool {
+ self.controller.wheels().get(i).map_or(false, |w| {
+ let u = w.direction_cs;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ true
+ })
+ }
+
+ pub fn set_wheel_direction_cs(&mut self, i: usize, value: &RawVector) {
+ if let Some(wheel) = self.controller.wheels_mut().get_mut(i) {
+ wheel.direction_cs = value.0;
+ }
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn wheel_axle_cs(&self, i: usize, scratch_buffer: &js_sys::Float32Array) -> bool {
+ self.controller.wheels().get(i).map_or(false, |w| {
+ let u = w.axle_cs;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ true
+ })
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn wheel_axle_cs(&self, i: usize, scratch_buffer: &js_sys::Float32Array) -> bool {
+ self.controller.wheels().get(i).map_or(false, |w| {
+ let u = w.axle_cs;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ true
+ })
+ }
+
+ pub fn set_wheel_axle_cs(&mut self, i: usize, value: &RawVector) {
+ if let Some(wheel) = self.controller.wheels_mut().get_mut(i) {
+ wheel.axle_cs = value.0;
+ }
+ }
+
+ pub fn wheel_friction_slip(&self, i: usize) -> Option {
+ self.controller.wheels().get(i).map(|w| w.friction_slip)
+ }
+ pub fn set_wheel_friction_slip(&mut self, i: usize, value: Real) {
+ if let Some(wheel) = self.controller.wheels_mut().get_mut(i) {
+ wheel.friction_slip = value;
+ }
+ }
+
+ pub fn wheel_side_friction_stiffness(&self, i: usize) -> Option {
+ self.controller
+ .wheels()
+ .get(i)
+ .map(|w| w.side_friction_stiffness)
+ }
+
+ pub fn set_wheel_side_friction_stiffness(&mut self, i: usize, stiffness: f32) {
+ if let Some(wheel) = self.controller.wheels_mut().get_mut(i) {
+ wheel.side_friction_stiffness = stiffness;
+ }
+ }
+
+ /*
+ * Getters only.
+ */
+ pub fn wheel_rotation(&self, i: usize) -> Option {
+ self.controller.wheels().get(i).map(|w| w.rotation)
+ }
+
+ pub fn wheel_forward_impulse(&self, i: usize) -> Option {
+ self.controller.wheels().get(i).map(|w| w.forward_impulse)
+ }
+
+ pub fn wheel_side_impulse(&self, i: usize) -> Option {
+ self.controller.wheels().get(i).map(|w| w.side_impulse)
+ }
+
+ pub fn wheel_suspension_force(&self, i: usize) -> Option {
+ self.controller
+ .wheels()
+ .get(i)
+ .map(|w| w.wheel_suspension_force)
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn wheel_contact_normal_ws(&self, i: usize, scratch_buffer: &js_sys::Float32Array) -> bool {
+ self.controller.wheels().get(i).map_or(false, |w| {
+ let u = w.raycast_info().contact_normal_ws;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ true
+ })
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn wheel_contact_normal_ws(&self, i: usize, scratch_buffer: &js_sys::Float32Array) -> bool {
+ self.controller.wheels().get(i).map_or(false, |w| {
+ let u = w.raycast_info().contact_normal_ws;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ true
+ })
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn wheel_contact_point_ws(&self, i: usize, scratch_buffer: &js_sys::Float32Array) -> bool {
+ self.controller.wheels().get(i).map_or(false, |w| {
+ let u = w.raycast_info().contact_point_ws;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ true
+ })
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn wheel_contact_point_ws(&self, i: usize, scratch_buffer: &js_sys::Float32Array) -> bool {
+ self.controller.wheels().get(i).map_or(false, |w| {
+ let u = w.raycast_info().contact_point_ws;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ true
+ })
+ }
+
+ pub fn wheel_suspension_length(&self, i: usize) -> Option {
+ self.controller
+ .wheels()
+ .get(i)
+ .map(|w| w.raycast_info().suspension_length)
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn wheel_hard_point_ws(&self, i: usize, scratch_buffer: &js_sys::Float32Array) -> bool {
+ self.controller.wheels().get(i).map_or(false, |w| {
+ let u = w.raycast_info().hard_point_ws;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ true
+ })
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn wheel_hard_point_ws(&self, i: usize, scratch_buffer: &js_sys::Float32Array) -> bool {
+ self.controller.wheels().get(i).map_or(false, |w| {
+ let u = w.raycast_info().hard_point_ws;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ true
+ })
+ }
+
+ pub fn wheel_is_in_contact(&self, i: usize) -> bool {
+ self.controller
+ .wheels()
+ .get(i)
+ .map(|w| w.raycast_info().is_in_contact)
+ .unwrap_or(false)
+ }
+
+ pub fn wheel_ground_object(&self, i: usize) -> Option {
+ self.controller
+ .wheels()
+ .get(i)
+ .and_then(|w| w.raycast_info().ground_object)
+ .map(|h| utils::flat_handle(h.0))
+ }
+}
diff --git a/typescript/src/dynamics/ccd_solver.rs b/typescript/src/dynamics/ccd_solver.rs
new file mode 100644
index 000000000..4c8b54f8c
--- /dev/null
+++ b/typescript/src/dynamics/ccd_solver.rs
@@ -0,0 +1,13 @@
+use rapier::dynamics::CCDSolver;
+use wasm_bindgen::prelude::*;
+
+#[wasm_bindgen]
+pub struct RawCCDSolver(pub(crate) CCDSolver);
+
+#[wasm_bindgen]
+impl RawCCDSolver {
+ #[wasm_bindgen(constructor)]
+ pub fn new() -> Self {
+ RawCCDSolver(CCDSolver::new())
+ }
+}
diff --git a/typescript/src/dynamics/impulse_joint.rs b/typescript/src/dynamics/impulse_joint.rs
new file mode 100644
index 000000000..e8b24510e
--- /dev/null
+++ b/typescript/src/dynamics/impulse_joint.rs
@@ -0,0 +1,314 @@
+use crate::dynamics::{RawImpulseJointSet, RawJointAxis, RawJointType, RawMotorModel};
+use crate::math::{RawRotation, RawVector};
+use crate::utils::{self, FlatHandle};
+use rapier::dynamics::JointAxis;
+use rapier::math::Pose;
+use wasm_bindgen::prelude::*;
+
+#[wasm_bindgen]
+impl RawImpulseJointSet {
+ /// The type of this joint.
+ pub fn jointType(&self, handle: FlatHandle) -> RawJointType {
+ self.map(handle, |j| j.data.locked_axes.into())
+ }
+
+ /// The unique integer identifier of the first rigid-body this joint it attached to.
+ pub fn jointBodyHandle1(&self, handle: FlatHandle) -> FlatHandle {
+ self.map(handle, |j| utils::flat_handle(j.body1().0))
+ }
+
+ /// The unique integer identifier of the second rigid-body this joint is attached to.
+ pub fn jointBodyHandle2(&self, handle: FlatHandle) -> FlatHandle {
+ self.map(handle, |j| utils::flat_handle(j.body2().0))
+ }
+
+ /// The angular part of the joint’s local frame relative to the first rigid-body it is attached to.
+ #[cfg(feature = "dim3")]
+ pub fn jointFrameX1(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) {
+ self.map(handle, |j| {
+ let u = j.data.local_frame1.rotation;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ scratch_buffer.set_index(3, u.w);
+ });
+ }
+
+ /// The angular part of the joint’s local frame relative to the second rigid-body it is attached to.
+ #[cfg(feature = "dim3")]
+ pub fn jointFrameX2(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) {
+ self.map(handle, |j| {
+ let u = j.data.local_frame2.rotation;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ scratch_buffer.set_index(3, u.w);
+ });
+ }
+
+ /// The position of the first anchor of this joint.
+ ///
+ /// The first anchor gives the position of the points application point on the
+ /// local frame of the first rigid-body it is attached to.
+ #[cfg(feature = "dim2")]
+ pub fn jointAnchor1(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) {
+ self.map(handle, |j| {
+ let u = j.data.local_frame1.translation;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ });
+ }
+
+ /// The position of the second anchor of this joint.
+ ///
+ /// The second anchor gives the position of the points application point on the
+ /// local frame of the second rigid-body it is attached to.
+ #[cfg(feature = "dim3")]
+ pub fn jointAnchor1(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) {
+ self.map(handle, |j| {
+ let u = j.data.local_frame1.translation;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ });
+ }
+
+ /// The position of the second anchor of this joint.
+ ///
+ /// The second anchor gives the position of the points application point on the
+ /// local frame of the second rigid-body it is attached to.
+ #[cfg(feature = "dim2")]
+ pub fn jointAnchor2(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) {
+ self.map(handle, |j| {
+ let u = j.data.local_frame2.translation;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ });
+ }
+
+ /// The position of the second anchor of this joint.
+ ///
+ /// The second anchor gives the position of the points application point on the
+ /// local frame of the second rigid-body it is attached to.
+ #[cfg(feature = "dim3")]
+ pub fn jointAnchor2(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) {
+ self.map(handle, |j| {
+ let u = j.data.local_frame2.translation;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ });
+ }
+
+ /// Sets the position of the first local anchor
+ pub fn jointSetAnchor1(&mut self, handle: FlatHandle, newPos: &RawVector) {
+ self.map_mut(handle, |j| {
+ j.data.set_local_anchor1(newPos.0.into());
+ });
+ }
+
+ /// Sets the position of the second local anchor
+ pub fn jointSetAnchor2(&mut self, handle: FlatHandle, newPos: &RawVector) {
+ self.map_mut(handle, |j| {
+ j.data.set_local_anchor2(newPos.0.into());
+ })
+ }
+
+ /// Sets the angular part of the joint's local frame relative to the first rigid-body.
+ pub fn jointSetFrameX1(&mut self, handle: FlatHandle, newRot: &RawRotation) {
+ self.map_mut(handle, |j| {
+ j.data.local_frame1.rotation = newRot.0;
+ });
+ }
+
+ /// Sets the angular part of the joint's local frame relative to the second rigid-body.
+ pub fn jointSetFrameX2(&mut self, handle: FlatHandle, newRot: &RawRotation) {
+ self.map_mut(handle, |j| {
+ j.data.local_frame2.rotation = newRot.0;
+ });
+ }
+
+ /// Sets the full local frame (anchor + rotation) for the first rigid-body attachment.
+ pub fn jointSetLocalFrame1(
+ &mut self,
+ handle: FlatHandle,
+ anchor: &RawVector,
+ rot: &RawRotation,
+ ) {
+ self.map_mut(handle, |j| {
+ j.data
+ .set_local_frame1(Pose::from_parts(anchor.0, rot.0));
+ });
+ }
+
+ /// Sets the full local frame (anchor + rotation) for the second rigid-body attachment.
+ pub fn jointSetLocalFrame2(
+ &mut self,
+ handle: FlatHandle,
+ anchor: &RawVector,
+ rot: &RawRotation,
+ ) {
+ self.map_mut(handle, |j| {
+ j.data
+ .set_local_frame2(Pose::from_parts(anchor.0, rot.0));
+ });
+ }
+
+ /// Are contacts between the rigid-bodies attached by this joint enabled?
+ pub fn jointContactsEnabled(&self, handle: FlatHandle) -> bool {
+ self.map(handle, |j| j.data.contacts_enabled)
+ }
+
+ /// Sets whether contacts are enabled between the rigid-bodies attached by this joint.
+ pub fn jointSetContactsEnabled(&mut self, handle: FlatHandle, enabled: bool) {
+ self.map_mut(handle, |j| {
+ j.data.contacts_enabled = enabled;
+ });
+ }
+
+ /// Are the limits for this joint enabled?
+ pub fn jointLimitsEnabled(&self, handle: FlatHandle, axis: RawJointAxis) -> bool {
+ self.map(handle, |j| {
+ j.data.limit_axes.contains(JointAxis::from(axis).into())
+ })
+ }
+
+ /// Return the lower limit along the given joint axis.
+ pub fn jointLimitsMin(&self, handle: FlatHandle, axis: RawJointAxis) -> f32 {
+ self.map(handle, |j| j.data.limits[axis as usize].min)
+ }
+
+ /// If this is a prismatic joint, returns its upper limit.
+ pub fn jointLimitsMax(&self, handle: FlatHandle, axis: RawJointAxis) -> f32 {
+ self.map(handle, |j| j.data.limits[axis as usize].max)
+ }
+
+ /// Enables and sets the joint limits
+ pub fn jointSetLimits(&mut self, handle: FlatHandle, axis: RawJointAxis, min: f32, max: f32) {
+ self.map_mut(handle, |j| {
+ j.data.set_limits(axis.into(), [min, max]);
+ });
+ }
+
+ pub fn jointConfigureMotorModel(
+ &mut self,
+ handle: FlatHandle,
+ axis: RawJointAxis,
+ model: RawMotorModel,
+ ) {
+ self.map_mut(handle, |j| {
+ j.data.motors[axis as usize].model = model.into()
+ })
+ }
+
+ pub fn jointSetMotorMaxForce(&mut self, handle: FlatHandle, axis: RawJointAxis, maxForce: f32) {
+ self.map_mut(handle, |j| {
+ j.data.set_motor_max_force(axis.into(), maxForce);
+ })
+ }
+
+ /*
+ #[cfg(feature = "dim3")]
+ pub fn jointConfigureBallMotorVelocity(
+ &mut self,
+ handle: FlatHandle,
+ vx: f32,
+ vy: f32,
+ vz: f32,
+ factor: f32,
+ ) {
+ let targetVel = Vector3::new(vx, vy, vz);
+
+ self.map_mut(handle, |j| match &mut j.params {
+ JointData::SphericalJoint(j) => j.configure_motor_velocity(targetVel, factor),
+ _ => {}
+ })
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn jointConfigureBallMotorPosition(
+ &mut self,
+ handle: FlatHandle,
+ qw: f32,
+ qx: f32,
+ qy: f32,
+ qz: f32,
+ stiffness: f32,
+ damping: f32,
+ ) {
+ let quat = Quaternion::new(qw, qx, qy, qz);
+
+ self.map_mut(handle, |j| match &mut j.params {
+ JointData::SphericalJoint(j) => {
+ if let Some(unit_quat) = UnitQuaternion::try_new(quat, 1.0e-5) {
+ j.configure_motor_position(unit_quat, stiffness, damping)
+ }
+ }
+ _ => {}
+ })
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn jointConfigureBallMotor(
+ &mut self,
+ handle: FlatHandle,
+ qw: f32,
+ qx: f32,
+ qy: f32,
+ qz: f32,
+ vx: f32,
+ vy: f32,
+ vz: f32,
+ stiffness: f32,
+ damping: f32,
+ ) {
+ let quat = Quaternion::new(qw, qx, qy, qz);
+ let vel = Vector3::new(vx, vy, vz);
+
+ self.map_mut(handle, |j| match &mut j.params {
+ JointData::SphericalJoint(j) => {
+ if let Some(unit_quat) = UnitQuaternion::try_new(quat, 1.0e-5) {
+ j.configure_motor(unit_quat, vel, stiffness, damping)
+ }
+ }
+ _ => {}
+ })
+ }
+ */
+
+ pub fn jointConfigureMotorVelocity(
+ &mut self,
+ handle: FlatHandle,
+ axis: RawJointAxis,
+ targetVel: f32,
+ factor: f32,
+ ) {
+ self.jointConfigureMotor(handle, axis, 0.0, targetVel, 0.0, factor)
+ }
+
+ pub fn jointConfigureMotorPosition(
+ &mut self,
+ handle: FlatHandle,
+ axis: RawJointAxis,
+ targetPos: f32,
+ stiffness: f32,
+ damping: f32,
+ ) {
+ self.jointConfigureMotor(handle, axis, targetPos, 0.0, stiffness, damping)
+ }
+
+ pub fn jointConfigureMotor(
+ &mut self,
+ handle: FlatHandle,
+ axis: RawJointAxis,
+ targetPos: f32,
+ targetVel: f32,
+ stiffness: f32,
+ damping: f32,
+ ) {
+ self.map_mut(handle, |j| {
+ j.data
+ .set_motor(axis.into(), targetPos, targetVel, stiffness, damping);
+ })
+ }
+}
diff --git a/typescript/src/dynamics/impulse_joint_set.rs b/typescript/src/dynamics/impulse_joint_set.rs
new file mode 100644
index 000000000..b7ba1bf08
--- /dev/null
+++ b/typescript/src/dynamics/impulse_joint_set.rs
@@ -0,0 +1,92 @@
+use crate::dynamics::RawGenericJoint;
+use crate::utils::{self, FlatHandle};
+use rapier::dynamics::{ImpulseJoint, ImpulseJointSet};
+use wasm_bindgen::prelude::*;
+
+#[wasm_bindgen]
+pub struct RawImpulseJointSet(pub(crate) ImpulseJointSet);
+
+impl RawImpulseJointSet {
+ pub(crate) fn map(&self, handle: FlatHandle, f: impl FnOnce(&ImpulseJoint) -> T) -> T {
+ let body = self.0.get(utils::impulse_joint_handle(handle)).expect(
+ "Invalid ImpulseJoint reference. It may have been removed from the physics World.",
+ );
+ f(body)
+ }
+
+ pub(crate) fn map_mut(
+ &mut self,
+ handle: FlatHandle,
+ f: impl FnOnce(&mut ImpulseJoint) -> T,
+ ) -> T {
+ let body = self
+ .0
+ .get_mut(utils::impulse_joint_handle(handle), true)
+ .expect(
+ "Invalid ImpulseJoint reference. It may have been removed from the physics World.",
+ );
+ f(body)
+ }
+}
+
+#[wasm_bindgen]
+impl RawImpulseJointSet {
+ #[wasm_bindgen(constructor)]
+ pub fn new() -> Self {
+ RawImpulseJointSet(ImpulseJointSet::new())
+ }
+
+ pub fn createJoint(
+ &mut self,
+ params: &RawGenericJoint,
+ parent1: FlatHandle,
+ parent2: FlatHandle,
+ wake_up: bool,
+ ) -> FlatHandle {
+ utils::flat_handle(
+ self.0
+ .insert(
+ utils::body_handle(parent1),
+ utils::body_handle(parent2),
+ params.0.clone(),
+ wake_up,
+ )
+ .0,
+ )
+ }
+
+ pub fn remove(&mut self, handle: FlatHandle, wakeUp: bool) {
+ let handle = utils::impulse_joint_handle(handle);
+ self.0.remove(handle, wakeUp);
+ }
+
+ pub fn len(&self) -> usize {
+ self.0.len()
+ }
+
+ pub fn contains(&self, handle: FlatHandle) -> bool {
+ self.0.get(utils::impulse_joint_handle(handle)).is_some()
+ }
+
+ /// Applies the given JavaScript function to the integer handle of each joint managed by this physics world.
+ ///
+ /// # Parameters
+ /// - `f(handle)`: the function to apply to the integer handle of each joint managed by this set. Called as `f(collider)`.
+ pub fn forEachJointHandle(&self, f: &js_sys::Function) {
+ let this = JsValue::null();
+ for (handle, _) in self.0.iter() {
+ let _ = f.call1(&this, &JsValue::from(utils::flat_handle(handle.0)));
+ }
+ }
+
+ /// Applies the given JavaScript function to the integer handle of each joint attached to the given rigid-body.
+ ///
+ /// # Parameters
+ /// - `f(handle)`: the function to apply to the integer handle of each joint attached to the rigid-body. Called as `f(collider)`.
+ pub fn forEachJointAttachedToRigidBody(&self, body: FlatHandle, f: &js_sys::Function) {
+ let this = JsValue::null();
+ for (_, _, handle, _) in self.0.attached_joints(utils::body_handle(body)) {
+ let _ = f.call1(&this, &JsValue::from(utils::flat_handle(handle.0)));
+ }
+ }
+}
diff --git a/typescript/src/dynamics/integration_parameters.rs b/typescript/src/dynamics/integration_parameters.rs
new file mode 100644
index 000000000..6aac0b517
--- /dev/null
+++ b/typescript/src/dynamics/integration_parameters.rs
@@ -0,0 +1,101 @@
+use rapier::dynamics::IntegrationParameters;
+use wasm_bindgen::prelude::*;
+
+#[wasm_bindgen]
+pub struct RawIntegrationParameters(pub(crate) IntegrationParameters);
+
+#[wasm_bindgen]
+impl RawIntegrationParameters {
+ #[wasm_bindgen(constructor)]
+ pub fn new() -> Self {
+ RawIntegrationParameters(IntegrationParameters::default())
+ }
+
+ #[wasm_bindgen(getter)]
+ pub fn dt(&self) -> f32 {
+ self.0.dt
+ }
+
+ #[wasm_bindgen(getter)]
+ pub fn contact_erp(&self) -> f32 {
+ self.0.contact_softness.erp(self.0.dt)
+ }
+
+ #[wasm_bindgen(getter)]
+ pub fn normalizedAllowedLinearError(&self) -> f32 {
+ self.0.normalized_allowed_linear_error
+ }
+
+ #[wasm_bindgen(getter)]
+ pub fn normalizedPredictionDistance(&self) -> f32 {
+ self.0.normalized_prediction_distance
+ }
+
+ #[wasm_bindgen(getter)]
+ pub fn numSolverIterations(&self) -> usize {
+ self.0.num_solver_iterations
+ }
+
+ #[wasm_bindgen(getter)]
+ pub fn numInternalPgsIterations(&self) -> usize {
+ self.0.num_internal_pgs_iterations
+ }
+
+ #[wasm_bindgen(getter)]
+ pub fn minIslandSize(&self) -> usize {
+ self.0.min_island_size
+ }
+
+ #[wasm_bindgen(getter)]
+ pub fn maxCcdSubsteps(&self) -> usize {
+ self.0.max_ccd_substeps
+ }
+
+ #[wasm_bindgen(getter)]
+ pub fn lengthUnit(&self) -> f32 {
+ self.0.length_unit
+ }
+
+ #[wasm_bindgen(setter)]
+ pub fn set_dt(&mut self, value: f32) {
+ self.0.dt = value;
+ }
+
+ #[wasm_bindgen(setter)]
+ pub fn set_contact_natural_frequency(&mut self, value: f32) {
+ self.0.contact_softness.natural_frequency = value
+ }
+
+ #[wasm_bindgen(setter)]
+ pub fn set_normalizedAllowedLinearError(&mut self, value: f32) {
+ self.0.normalized_allowed_linear_error = value
+ }
+
+ #[wasm_bindgen(setter)]
+ pub fn set_normalizedPredictionDistance(&mut self, value: f32) {
+ self.0.normalized_prediction_distance = value
+ }
+
+ #[wasm_bindgen(setter)]
+ pub fn set_numSolverIterations(&mut self, value: usize) {
+ self.0.num_solver_iterations = value;
+ }
+ #[wasm_bindgen(setter)]
+ pub fn set_numInternalPgsIterations(&mut self, value: usize) {
+ self.0.num_internal_pgs_iterations = value;
+ }
+ #[wasm_bindgen(setter)]
+ pub fn set_minIslandSize(&mut self, value: usize) {
+ self.0.min_island_size = value
+ }
+
+ #[wasm_bindgen(setter)]
+ pub fn set_maxCcdSubsteps(&mut self, value: usize) {
+ self.0.max_ccd_substeps = value
+ }
+
+ #[wasm_bindgen(setter)]
+ pub fn set_lengthUnit(&mut self, value: f32) {
+ self.0.length_unit = value
+ }
+}
diff --git a/typescript/src/dynamics/island_manager.rs b/typescript/src/dynamics/island_manager.rs
new file mode 100644
index 000000000..7b4cfae61
--- /dev/null
+++ b/typescript/src/dynamics/island_manager.rs
@@ -0,0 +1,31 @@
+use crate::utils;
+use rapier::dynamics::IslandManager;
+use wasm_bindgen::prelude::*;
+
+#[wasm_bindgen]
+pub struct RawIslandManager(pub(crate) IslandManager);
+
+#[wasm_bindgen]
+impl RawIslandManager {
+ #[wasm_bindgen(constructor)]
+ pub fn new() -> Self {
+ RawIslandManager(IslandManager::new())
+ }
+
+ /// Applies the given JavaScript function to the integer handle of each active rigid-body
+ /// managed by this island manager.
+ ///
+ /// After a short time of inactivity, a rigid-body is automatically deactivated ("asleep") by
+ /// the physics engine in order to save computational power. A sleeping rigid-body never moves
+ /// unless it is moved manually by the user.
+ ///
+ /// # Parameters
+ /// - `f(handle)`: the function to apply to the integer handle of each active rigid-body managed by this
+ /// set. Called as `f(collider)`.
+ pub fn forEachActiveRigidBodyHandle(&self, f: &js_sys::Function) {
+ let this = JsValue::null();
+ for handle in self.0.active_bodies() {
+ let _ = f.call1(&this, &JsValue::from(utils::flat_handle(handle.0)));
+ }
+ }
+}
diff --git a/typescript/src/dynamics/joint.rs b/typescript/src/dynamics/joint.rs
new file mode 100644
index 000000000..d6199db66
--- /dev/null
+++ b/typescript/src/dynamics/joint.rs
@@ -0,0 +1,337 @@
+use crate::math::{RawRotation, RawVector};
+use rapier::dynamics::{
+ FixedJointBuilder, GenericJoint, JointAxesMask, JointAxis, MotorModel, PrismaticJointBuilder,
+ RevoluteJointBuilder, RopeJointBuilder, SpringJointBuilder,
+};
+#[cfg(feature = "dim3")]
+use rapier::dynamics::{GenericJointBuilder, SphericalJointBuilder};
+use rapier::math::Pose;
+use wasm_bindgen::prelude::*;
+
+#[wasm_bindgen]
+#[cfg(feature = "dim2")]
+pub enum RawJointType {
+ Revolute,
+ Fixed,
+ Prismatic,
+ Rope,
+ Spring,
+ Generic,
+}
+
+#[wasm_bindgen]
+#[cfg(feature = "dim3")]
+pub enum RawJointType {
+ Revolute,
+ Fixed,
+ Prismatic,
+ Rope,
+ Spring,
+ Spherical,
+ Generic,
+}
+
+/// The type of this joint.
+#[cfg(feature = "dim2")]
+impl From for RawJointType {
+ fn from(ty: JointAxesMask) -> RawJointType {
+ let rev_axes = JointAxesMask::LIN_X | JointAxesMask::LIN_Y;
+ let pri_axes = JointAxesMask::LIN_Y | JointAxesMask::ANG_X;
+ let fix_axes = JointAxesMask::LIN_X | JointAxesMask::LIN_Y | JointAxesMask::ANG_X;
+
+ if ty == rev_axes {
+ RawJointType::Revolute
+ } else if ty == pri_axes {
+ RawJointType::Prismatic
+ } else if ty == fix_axes {
+ RawJointType::Fixed
+ } else {
+ RawJointType::Generic
+ }
+ }
+}
+
+/// The type of this joint.
+#[cfg(feature = "dim3")]
+impl From for RawJointType {
+ fn from(ty: JointAxesMask) -> RawJointType {
+ let rev_axes = JointAxesMask::LIN_X
+ | JointAxesMask::LIN_Y
+ | JointAxesMask::LIN_Z
+ | JointAxesMask::ANG_Y
+ | JointAxesMask::ANG_Z;
+ let pri_axes = JointAxesMask::LIN_Y
+ | JointAxesMask::LIN_Z
+ | JointAxesMask::ANG_X
+ | JointAxesMask::ANG_Y
+ | JointAxesMask::ANG_Z;
+ let sph_axes = JointAxesMask::ANG_X | JointAxesMask::ANG_Y | JointAxesMask::ANG_Z;
+ let fix_axes = JointAxesMask::LIN_X
+ | JointAxesMask::LIN_Y
+ | JointAxesMask::LIN_Z
+ | JointAxesMask::ANG_X
+ | JointAxesMask::ANG_Y
+ | JointAxesMask::ANG_Z;
+
+ if ty == rev_axes {
+ RawJointType::Revolute
+ } else if ty == pri_axes {
+ RawJointType::Prismatic
+ } else if ty == sph_axes {
+ RawJointType::Spherical
+ } else if ty == fix_axes {
+ RawJointType::Fixed
+ } else {
+ RawJointType::Generic
+ }
+ }
+}
+
+#[wasm_bindgen]
+pub enum RawMotorModel {
+ AccelerationBased,
+ ForceBased,
+}
+
+impl From for MotorModel {
+ fn from(model: RawMotorModel) -> MotorModel {
+ match model {
+ RawMotorModel::AccelerationBased => MotorModel::AccelerationBased,
+ RawMotorModel::ForceBased => MotorModel::ForceBased,
+ }
+ }
+}
+
+#[cfg(feature = "dim2")]
+#[wasm_bindgen]
+#[derive(Copy, Clone)]
+pub enum RawJointAxis {
+ LinX,
+ LinY,
+ AngX,
+}
+
+#[cfg(feature = "dim3")]
+#[wasm_bindgen]
+#[derive(Copy, Clone)]
+pub enum RawJointAxis {
+ LinX,
+ LinY,
+ LinZ,
+ AngX,
+ AngY,
+ AngZ,
+}
+
+impl From for JointAxis {
+ fn from(axis: RawJointAxis) -> JointAxis {
+ match axis {
+ RawJointAxis::LinX => JointAxis::LinX,
+ RawJointAxis::LinY => JointAxis::LinY,
+ #[cfg(feature = "dim3")]
+ RawJointAxis::LinZ => JointAxis::LinZ,
+ RawJointAxis::AngX => JointAxis::AngX,
+ #[cfg(feature = "dim3")]
+ RawJointAxis::AngY => JointAxis::AngY,
+ #[cfg(feature = "dim3")]
+ RawJointAxis::AngZ => JointAxis::AngZ,
+ }
+ }
+}
+
+#[wasm_bindgen]
+pub struct RawGenericJoint(pub(crate) GenericJoint);
+
+#[wasm_bindgen]
+impl RawGenericJoint {
+ /// Creates a new joint descriptor that builds generic joints.
+ ///
+ /// Generic joints allow arbitrary axes of freedom to be selected
+ /// for the joint from the available 6 degrees of freedom.
+ #[cfg(feature = "dim3")]
+ pub fn generic(
+ anchor1: &RawVector,
+ anchor2: &RawVector,
+ axis: &RawVector,
+ lockedAxes: u8,
+ ) -> Option {
+ let axesMask: JointAxesMask = JointAxesMask::from_bits(lockedAxes)?;
+ let axis = axis.0.try_normalize()?;
+ let joint: GenericJoint = GenericJointBuilder::new(axesMask)
+ .local_anchor1(anchor1.0.into())
+ .local_anchor2(anchor2.0.into())
+ .local_axis1(axis)
+ .local_axis2(axis)
+ .into();
+ Some(Self(joint))
+ }
+
+ pub fn spring(
+ rest_length: f32,
+ stiffness: f32,
+ damping: f32,
+ anchor1: &RawVector,
+ anchor2: &RawVector,
+ ) -> Self {
+ Self(
+ SpringJointBuilder::new(rest_length, stiffness, damping)
+ .local_anchor1(anchor1.0.into())
+ .local_anchor2(anchor2.0.into())
+ .into(),
+ )
+ }
+
+ pub fn rope(length: f32, anchor1: &RawVector, anchor2: &RawVector) -> Self {
+ Self(
+ RopeJointBuilder::new(length)
+ .local_anchor1(anchor1.0.into())
+ .local_anchor2(anchor2.0.into())
+ .into(),
+ )
+ }
+
+ /// Create a new joint descriptor that builds spherical joints.
+ ///
+ /// A spherical joints allows three relative rotational degrees of freedom
+ /// by preventing any relative translation between the anchors of the
+ /// two attached rigid-bodies.
+ #[cfg(feature = "dim3")]
+ pub fn spherical(anchor1: &RawVector, anchor2: &RawVector) -> Self {
+ Self(
+ SphericalJointBuilder::new()
+ .local_anchor1(anchor1.0.into())
+ .local_anchor2(anchor2.0.into())
+ .into(),
+ )
+ }
+
+ /// Creates a new joint descriptor that builds a Prismatic joint.
+ ///
+ /// A prismatic joint removes all the degrees of freedom between the
+ /// affected bodies, except for the translation along one axis.
+ ///
+ /// Returns `None` if any of the provided axes cannot be normalized.
+ #[cfg(feature = "dim2")]
+ pub fn prismatic(
+ anchor1: &RawVector,
+ anchor2: &RawVector,
+ axis: &RawVector,
+ limitsEnabled: bool,
+ limitsMin: f32,
+ limitsMax: f32,
+ ) -> Option {
+ let axis = axis.0.try_normalize()?;
+ let mut joint = PrismaticJointBuilder::new(axis)
+ .local_anchor1(anchor1.0.into())
+ .local_anchor2(anchor2.0.into());
+
+ if limitsEnabled {
+ joint = joint.limits([limitsMin, limitsMax]);
+ }
+
+ Some(Self(joint.into()))
+ }
+
+ /// Creates a new joint descriptor that builds a Prismatic joint.
+ ///
+ /// A prismatic joint removes all the degrees of freedom between the
+ /// affected bodies, except for the translation along one axis.
+ ///
+ /// Returns `None` if any of the provided axes cannot be normalized.
+ #[cfg(feature = "dim3")]
+ pub fn prismatic(
+ anchor1: &RawVector,
+ anchor2: &RawVector,
+ axis: &RawVector,
+ limitsEnabled: bool,
+ limitsMin: f32,
+ limitsMax: f32,
+ ) -> Option {
+ let axis = axis.0.try_normalize()?;
+ let mut joint = PrismaticJointBuilder::new(axis)
+ .local_anchor1(anchor1.0.into())
+ .local_anchor2(anchor2.0.into());
+
+ if limitsEnabled {
+ joint = joint.limits([limitsMin, limitsMax]);
+ }
+
+ Some(Self(joint.into()))
+ }
+
+ /// Creates a new joint descriptor that builds a Fixed joint.
+ ///
+ /// A fixed joint removes all the degrees of freedom between the affected bodies.
+ pub fn fixed(
+ anchor1: &RawVector,
+ axes1: &RawRotation,
+ anchor2: &RawVector,
+ axes2: &RawRotation,
+ ) -> RawGenericJoint {
+ let pos1 = Pose::from_parts(anchor1.0, axes1.0);
+ let pos2 = Pose::from_parts(anchor2.0, axes2.0);
+ Self(
+ FixedJointBuilder::new()
+ .local_frame1(pos1)
+ .local_frame2(pos2)
+ .into(),
+ )
+ }
+
+ /// Create a new joint descriptor that builds Revolute joints.
+ ///
+ /// A revolute joint removes all degrees of freedom between the affected
+ /// bodies except for the rotation.
+ #[cfg(feature = "dim2")]
+ pub fn revolute(anchor1: &RawVector, anchor2: &RawVector) -> Option {
+ Some(Self(
+ RevoluteJointBuilder::new()
+ .local_anchor1(anchor1.0.into())
+ .local_anchor2(anchor2.0.into())
+ .into(),
+ ))
+ }
+
+ /// Create a new joint descriptor that builds Revolute joints.
+ ///
+ /// A revolute joint removes all degrees of freedom between the affected
+ /// bodies except for the rotation along one axis.
+ #[cfg(feature = "dim3")]
+ pub fn revolute(
+ anchor1: &RawVector,
+ anchor2: &RawVector,
+ axis: &RawVector,
+ ) -> Option {
+ let axis = axis.0.try_normalize()?;
+ Some(Self(
+ RevoluteJointBuilder::new(axis)
+ .local_anchor1(anchor1.0.into())
+ .local_anchor2(anchor2.0.into())
+ .into(),
+ ))
+ }
+
+ /// Create a new joint descriptor that builds Revolute joints with
+ /// independent local axes for each attached rigid-body.
+ ///
+ /// This is equivalent to a revolute generic joint with all linear axes
+ /// locked and only angular X free, but it preserves the local hinge axis
+ /// on each body instead of assuming they are identical.
+ #[cfg(feature = "dim3")]
+ pub fn revoluteWithAxes(
+ anchor1: &RawVector,
+ anchor2: &RawVector,
+ axis1: &RawVector,
+ axis2: &RawVector,
+ ) -> Option {
+ let axis1 = axis1.0.try_normalize()?;
+ let axis2 = axis2.0.try_normalize()?;
+ let joint: GenericJoint = GenericJointBuilder::new(JointAxesMask::LOCKED_REVOLUTE_AXES)
+ .local_anchor1(anchor1.0.into())
+ .local_anchor2(anchor2.0.into())
+ .local_axis1(axis1)
+ .local_axis2(axis2)
+ .into();
+ Some(Self(joint))
+ }
+}
diff --git a/typescript/src/dynamics/mod.rs b/typescript/src/dynamics/mod.rs
new file mode 100644
index 000000000..36cc7eaa6
--- /dev/null
+++ b/typescript/src/dynamics/mod.rs
@@ -0,0 +1,20 @@
+//! Structures related to dynamics: bodies, joints, etc.
+
+pub use self::ccd_solver::*;
+pub use self::impulse_joint_set::*;
+pub use self::integration_parameters::*;
+pub use self::island_manager::*;
+pub use self::joint::*;
+pub use self::multibody_joint_set::*;
+pub use self::rigid_body_set::*;
+
+mod ccd_solver;
+mod impulse_joint;
+mod impulse_joint_set;
+mod integration_parameters;
+mod island_manager;
+mod joint;
+mod multibody_joint;
+mod multibody_joint_set;
+mod rigid_body;
+mod rigid_body_set;
diff --git a/typescript/src/dynamics/multibody_joint.rs b/typescript/src/dynamics/multibody_joint.rs
new file mode 100644
index 000000000..9a95f0d53
--- /dev/null
+++ b/typescript/src/dynamics/multibody_joint.rs
@@ -0,0 +1,196 @@
+use crate::dynamics::{RawJointAxis, RawJointType, RawMultibodyJointSet};
+use crate::math::{RawRotation, RawVector};
+use crate::utils::FlatHandle;
+use rapier::dynamics::JointAxis;
+use wasm_bindgen::prelude::*;
+
+#[wasm_bindgen]
+impl RawMultibodyJointSet {
+ /// The type of this joint.
+ pub fn jointType(&self, handle: FlatHandle) -> RawJointType {
+ self.map(handle, |j| j.data.locked_axes.into())
+ }
+
+ // /// The unique integer identifier of the first rigid-body this joint it attached to.
+ // pub fn jointBodyHandle1(&self, handle: FlatHandle) -> u32 {
+ // self.map(handle, |j| j.body1.into_raw_parts().0)
+ // }
+ //
+ // /// The unique integer identifier of the second rigid-body this joint is attached to.
+ // pub fn jointBodyHandle2(&self, handle: FlatHandle) -> u32 {
+ // self.map(handle, |j| j.body2.into_raw_parts().0)
+ // }
+
+ /// The angular part of the joint’s local frame relative to the first rigid-body it is attached to.
+ pub fn jointFrameX1(&self, handle: FlatHandle) -> RawRotation {
+ self.map(handle, |j| j.data.local_frame1.rotation.into())
+ }
+
+ /// The angular part of the joint’s local frame relative to the second rigid-body it is attached to.
+ pub fn jointFrameX2(&self, handle: FlatHandle) -> RawRotation {
+ self.map(handle, |j| j.data.local_frame2.rotation.into())
+ }
+
+ /// The position of the first anchor of this joint.
+ ///
+ /// The first anchor gives the position of the points application point on the
+ /// local frame of the first rigid-body it is attached to.
+ pub fn jointAnchor1(&self, handle: FlatHandle) -> RawVector {
+ self.map(handle, |j| j.data.local_frame1.translation.into())
+ }
+
+ /// The position of the second anchor of this joint.
+ ///
+ /// The second anchor gives the position of the points application point on the
+ /// local frame of the second rigid-body it is attached to.
+ pub fn jointAnchor2(&self, handle: FlatHandle) -> RawVector {
+ self.map(handle, |j| j.data.local_frame2.translation.into())
+ }
+
+ /// Are contacts between the rigid-bodies attached by this joint enabled?
+ pub fn jointContactsEnabled(&self, handle: FlatHandle) -> bool {
+ self.map(handle, |j| j.data.contacts_enabled)
+ }
+
+ /// Sets whether contacts are enabled between the rigid-bodies attached by this joint.
+ pub fn jointSetContactsEnabled(&mut self, handle: FlatHandle, enabled: bool) {
+ self.map_mut(handle, |j| {
+ j.data.contacts_enabled = enabled;
+ });
+ }
+
+ /// Are the limits for this joint enabled?
+ pub fn jointLimitsEnabled(&self, handle: FlatHandle, axis: RawJointAxis) -> bool {
+ self.map(handle, |j| {
+ j.data.limit_axes.contains(JointAxis::from(axis).into())
+ })
+ }
+
+ /// Return the lower limit along the given joint axis.
+ pub fn jointLimitsMin(&self, handle: FlatHandle, axis: RawJointAxis) -> f32 {
+ self.map(handle, |j| j.data.limits[axis as usize].min)
+ }
+
+ /// If this is a prismatic joint, returns its upper limit.
+ pub fn jointLimitsMax(&self, handle: FlatHandle, axis: RawJointAxis) -> f32 {
+ self.map(handle, |j| j.data.limits[axis as usize].max)
+ }
+
+ // pub fn jointConfigureMotorModel(
+ // &mut self,
+ // handle: FlatHandle,
+ // axis: RawJointAxis,
+ // model: RawMotorModel,
+ // ) {
+ // self.map_mut(handle, |j| {
+ // j.data.motors[axis as usize].model = model.into()
+ // })
+ // }
+
+ /*
+ #[cfg(feature = "dim3")]
+ pub fn jointConfigureBallMotorVelocity(
+ &mut self,
+ handle: FlatHandle,
+ vx: f32,
+ vy: f32,
+ vz: f32,
+ factor: f32,
+ ) {
+ let targetVel = Vector3::new(vx, vy, vz);
+
+ self.map_mut(handle, |j| match &mut j.params {
+ JointData::SphericalJoint(j) => j.configure_motor_velocity(targetVel, factor),
+ _ => {}
+ })
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn jointConfigureBallMotorPosition(
+ &mut self,
+ handle: FlatHandle,
+ qw: f32,
+ qx: f32,
+ qy: f32,
+ qz: f32,
+ stiffness: f32,
+ damping: f32,
+ ) {
+ let quat = Quaternion::new(qw, qx, qy, qz);
+
+ self.map_mut(handle, |j| match &mut j.params {
+ JointData::SphericalJoint(j) => {
+ if let Some(unit_quat) = UnitQuaternion::try_new(quat, 1.0e-5) {
+ j.configure_motor_position(unit_quat, stiffness, damping)
+ }
+ }
+ _ => {}
+ })
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn jointConfigureBallMotor(
+ &mut self,
+ handle: FlatHandle,
+ qw: f32,
+ qx: f32,
+ qy: f32,
+ qz: f32,
+ vx: f32,
+ vy: f32,
+ vz: f32,
+ stiffness: f32,
+ damping: f32,
+ ) {
+ let quat = Quaternion::new(qw, qx, qy, qz);
+ let vel = Vector3::new(vx, vy, vz);
+
+ self.map_mut(handle, |j| match &mut j.params {
+ JointData::SphericalJoint(j) => {
+ if let Some(unit_quat) = UnitQuaternion::try_new(quat, 1.0e-5) {
+ j.configure_motor(unit_quat, vel, stiffness, damping)
+ }
+ }
+ _ => {}
+ })
+ }
+ */
+
+ // pub fn jointConfigureMotorVelocity(
+ // &mut self,
+ // handle: FlatHandle,
+ // axis: RawJointAxis,
+ // targetVel: f32,
+ // factor: f32,
+ // ) {
+ // self.jointConfigureMotor(handle, axis, 0.0, targetVel, 0.0, factor)
+ // }
+ //
+ // pub fn jointConfigureMotorPosition(
+ // &mut self,
+ // handle: FlatHandle,
+ // axis: RawJointAxis,
+ // targetPos: f32,
+ // stiffness: f32,
+ // damping: f32,
+ // ) {
+ // self.jointConfigureMotor(handle, axis, targetPos, 0.0, stiffness, damping)
+ // }
+
+ // pub fn jointConfigureMotor(
+ // &mut self,
+ // handle: FlatHandle,
+ // axis: RawJointAxis,
+ // targetPos: f32,
+ // targetVel: f32,
+ // stiffness: f32,
+ // damping: f32,
+ // ) {
+ // self.map_mut(handle, |j| {
+ // j.data.motors[axis as usize].target_pos = targetPos;
+ // j.data.motors[axis as usize].target_vel = targetVel;
+ // j.data.motors[axis as usize].stiffness = stiffness;
+ // j.data.motors[axis as usize].damping = damping;
+ // })
+ // }
+}
diff --git a/typescript/src/dynamics/multibody_joint_set.rs b/typescript/src/dynamics/multibody_joint_set.rs
new file mode 100644
index 000000000..c7f4839e0
--- /dev/null
+++ b/typescript/src/dynamics/multibody_joint_set.rs
@@ -0,0 +1,85 @@
+use crate::dynamics::RawGenericJoint;
+use crate::utils::{self, FlatHandle};
+use rapier::dynamics::{MultibodyJoint, MultibodyJointSet};
+use wasm_bindgen::prelude::*;
+
+#[wasm_bindgen]
+pub struct RawMultibodyJointSet(pub(crate) MultibodyJointSet);
+
+impl RawMultibodyJointSet {
+ pub(crate) fn map(&self, handle: FlatHandle, f: impl FnOnce(&MultibodyJoint) -> T) -> T {
+ let (body, link_id) = self
+ .0
+ .get(utils::multibody_joint_handle(handle))
+ .expect("Invalid Joint reference. It may have been removed from the physics World.");
+ f(body.link(link_id).unwrap().joint())
+ }
+
+ pub(crate) fn map_mut(
+ &mut self,
+ handle: FlatHandle,
+ f: impl FnOnce(&mut MultibodyJoint) -> T,
+ ) -> T {
+ let (body, link_id) = self
+ .0
+ .get_mut(utils::multibody_joint_handle(handle))
+ .expect("Invalid Joint reference. It may have been removed from the physics World.");
+ f(&mut body.link_mut(link_id).unwrap().joint)
+ }
+}
+
+#[wasm_bindgen]
+impl RawMultibodyJointSet {
+ #[wasm_bindgen(constructor)]
+ pub fn new() -> Self {
+ RawMultibodyJointSet(MultibodyJointSet::new())
+ }
+
+ pub fn createJoint(
+ &mut self,
+ params: &RawGenericJoint,
+ parent1: FlatHandle,
+ parent2: FlatHandle,
+ wakeUp: bool,
+ ) -> FlatHandle {
+ // TODO: avoid the unwrap?
+ let parent1 = utils::body_handle(parent1);
+ let parent2 = utils::body_handle(parent2);
+
+ self.0
+ .insert(parent1, parent2, params.0.clone(), wakeUp)
+ .map(|h| utils::flat_handle(h.0))
+ .unwrap_or(FlatHandle::MAX)
+ }
+
+ pub fn remove(&mut self, handle: FlatHandle, wakeUp: bool) {
+ let handle = utils::multibody_joint_handle(handle);
+ self.0.remove(handle, wakeUp);
+ }
+
+ pub fn contains(&self, handle: FlatHandle) -> bool {
+ self.0.get(utils::multibody_joint_handle(handle)).is_some()
+ }
+
+ /// Applies the given JavaScript function to the integer handle of each joint managed by this physics world.
+ ///
+ /// # Parameters
+ /// - `f(handle)`: the function to apply to the integer handle of each joint managed by this set. Called as `f(collider)`.
+ pub fn forEachJointHandle(&self, f: &js_sys::Function) {
+ let this = JsValue::null();
+ for (handle, _, _, _) in self.0.iter() {
+ let _ = f.call1(&this, &JsValue::from(utils::flat_handle(handle.0)));
+ }
+ }
+
+ /// Applies the given JavaScript function to the integer handle of each joint attached to the given rigid-body.
+ ///
+ /// # Parameters
+ /// - `f(handle)`: the function to apply to the integer handle of each joint attached to the rigid-body. Called as `f(collider)`.
+ pub fn forEachJointAttachedToRigidBody(&self, body: FlatHandle, f: &js_sys::Function) {
+ let this = JsValue::null();
+ for (_, _, handle) in self.0.attached_joints(utils::body_handle(body)) {
+ let _ = f.call1(&this, &JsValue::from(utils::flat_handle(handle.0)));
+ }
+ }
+}
diff --git a/typescript/src/dynamics/rigid_body.rs b/typescript/src/dynamics/rigid_body.rs
new file mode 100644
index 000000000..0b12e1964
--- /dev/null
+++ b/typescript/src/dynamics/rigid_body.rs
@@ -0,0 +1,1036 @@
+use crate::dynamics::{RawRigidBodySet, RawRigidBodyType};
+use crate::geometry::RawColliderSet;
+#[cfg(feature = "dim3")]
+use crate::math::RawRotation;
+use crate::math::RawVector;
+use crate::utils::{self, FlatHandle};
+use rapier::dynamics::MassProperties;
+use rapier::math::{Rotation, Vector};
+use wasm_bindgen::prelude::*;
+
+#[wasm_bindgen]
+impl RawRigidBodySet {
+ /// The world-space translation of this rigid-body.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim2")]
+ pub fn rbTranslation(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) {
+ self.map(handle, |rb| {
+ let u = rb.position().translation;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ });
+ }
+
+ /// The world-space translation of this rigid-body.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim3")]
+ pub fn rbTranslation(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) {
+ self.map(handle, |rb| {
+ let u = rb.position().translation;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ });
+ }
+
+ /// The world-space orientation of this rigid-body.
+ #[cfg(feature = "dim2")]
+ pub fn rbRotation(&self, handle: FlatHandle) -> f32 {
+ self.map(handle, |rb| rb.position().rotation.angle())
+ }
+
+ /// The world-space orientation of this rigid-body.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim3")]
+ pub fn rbRotation(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) {
+ self.map(handle, |rb| {
+ let u = rb.position().rotation;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ scratch_buffer.set_index(3, u.w);
+ });
+ }
+
+ /// Put the given rigid-body to sleep.
+ pub fn rbSleep(&mut self, handle: FlatHandle) {
+ self.map_mut(handle, |rb| rb.sleep());
+ }
+
+ /// Is this rigid-body sleeping?
+ pub fn rbIsSleeping(&self, handle: FlatHandle) -> bool {
+ self.map(handle, |rb| rb.is_sleeping())
+ }
+
+ /// Is the velocity of this rigid-body not zero?
+ pub fn rbIsMoving(&self, handle: FlatHandle) -> bool {
+ self.map(handle, |rb| rb.is_moving())
+ }
+
+ /// The world-space predicted translation of this rigid-body.
+ ///
+ /// If this rigid-body is kinematic this value is set by the `setNextKinematicTranslation`
+ /// method and is used for estimating the kinematic body velocity at the next timestep.
+ /// For non-kinematic bodies, this value is currently unspecified.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim2")]
+ pub fn rbNextTranslation(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) {
+ self.map(handle, |rb| {
+ let u = rb.next_position().translation;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ });
+ }
+
+ /// The world-space predicted translation of this rigid-body.
+ ///
+ /// If this rigid-body is kinematic this value is set by the `setNextKinematicTranslation`
+ /// method and is used for estimating the kinematic body velocity at the next timestep.
+ /// For non-kinematic bodies, this value is currently unspecified.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim3")]
+ pub fn rbNextTranslation(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) {
+ self.map(handle, |rb| {
+ let u = rb.next_position().translation;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ });
+ }
+
+ /// The world-space predicted orientation of this rigid-body.
+ ///
+ /// If this rigid-body is kinematic this value is set by the `setNextKinematicRotation`
+ /// method and is used for estimating the kinematic body velocity at the next timestep.
+ /// For non-kinematic bodies, this value is currently unspecified.
+ #[cfg(feature = "dim2")]
+ pub fn rbNextRotation(&self, handle: FlatHandle) -> f32 {
+ self.map(handle, |rb| rb.next_position().rotation.angle())
+ }
+
+ /// The world-space predicted orientation of this rigid-body.
+ ///
+ /// If this rigid-body is kinematic this value is set by the `setNextKinematicRotation`
+ /// method and is used for estimating the kinematic body velocity at the next timestep.
+ /// For non-kinematic bodies, this value is currently unspecified.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim3")]
+ pub fn rbNextRotation(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) {
+ self.map(handle, |rb| {
+ let u = rb.next_position().rotation;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ scratch_buffer.set_index(3, u.w);
+ });
+ }
+
+ /// Sets the translation of this rigid-body.
+ ///
+ /// # Parameters
+ /// - `x`: the world-space position of the rigid-body along the `x` axis.
+ /// - `y`: the world-space position of the rigid-body along the `y` axis.
+ /// - `z`: the world-space position of the rigid-body along the `z` axis.
+ /// - `wakeUp`: forces the rigid-body to wake-up so it is properly affected by forces if it
+ /// wasn't moving before modifying its position.
+ #[cfg(feature = "dim3")]
+ pub fn rbSetTranslation(&mut self, handle: FlatHandle, x: f32, y: f32, z: f32, wakeUp: bool) {
+ self.map_mut(handle, |rb| {
+ rb.set_translation(Vector::new(x, y, z), wakeUp);
+ })
+ }
+
+ /// Sets the translation of this rigid-body.
+ ///
+ /// # Parameters
+ /// - `x`: the world-space position of the rigid-body along the `x` axis.
+ /// - `y`: the world-space position of the rigid-body along the `y` axis.
+ /// - `wakeUp`: forces the rigid-body to wake-up so it is properly affected by forces if it
+ /// wasn't moving before modifying its position.
+ #[cfg(feature = "dim2")]
+ pub fn rbSetTranslation(&mut self, handle: FlatHandle, x: f32, y: f32, wakeUp: bool) {
+ self.map_mut(handle, |rb| {
+ rb.set_translation(Vector::new(x, y), wakeUp);
+ })
+ }
+
+ /// Sets the rotation quaternion of this rigid-body.
+ ///
+ /// This does nothing if a zero quaternion is provided.
+ ///
+ /// # Parameters
+ /// - `x`: the first vector component of the quaternion.
+ /// - `y`: the second vector component of the quaternion.
+ /// - `z`: the third vector component of the quaternion.
+ /// - `w`: the scalar component of the quaternion.
+ /// - `wakeUp`: forces the rigid-body to wake-up so it is properly affected by forces if it
+ /// wasn't moving before modifying its position.
+ #[cfg(feature = "dim3")]
+ pub fn rbSetRotation(
+ &mut self,
+ handle: FlatHandle,
+ x: f32,
+ y: f32,
+ z: f32,
+ w: f32,
+ wakeUp: bool,
+ ) {
+ let q = Rotation::from_xyzw(x, y, z, w);
+ if q.length_squared() > 0.0 {
+ let q = q.normalize();
+ self.map_mut(handle, |rb| rb.set_rotation(q, wakeUp))
+ }
+ }
+
+ /// Sets the rotation angle of this rigid-body.
+ ///
+ /// # Parameters
+ /// - `angle`: the rotation angle, in radians.
+ /// - `wakeUp`: forces the rigid-body to wake-up so it is properly affected by forces if it
+ /// wasn't moving before modifying its position.
+ #[cfg(feature = "dim2")]
+ pub fn rbSetRotation(&mut self, handle: FlatHandle, angle: f32, wakeUp: bool) {
+ self.map_mut(handle, |rb| {
+ rb.set_rotation(Rotation::new(angle), wakeUp)
+ })
+ }
+
+ /// Sets the linear velocity of this rigid-body.
+ pub fn rbSetLinvel(&mut self, handle: FlatHandle, linvel: &RawVector, wakeUp: bool) {
+ self.map_mut(handle, |rb| {
+ rb.set_linvel(linvel.0, wakeUp);
+ });
+ }
+
+ /// Sets the angular velocity of this rigid-body.
+ #[cfg(feature = "dim2")]
+ pub fn rbSetAngvel(&mut self, handle: FlatHandle, angvel: f32, wakeUp: bool) {
+ self.map_mut(handle, |rb| {
+ rb.set_angvel(angvel, wakeUp);
+ });
+ }
+
+ /// Sets the angular velocity of this rigid-body.
+ #[cfg(feature = "dim3")]
+ pub fn rbSetAngvel(&mut self, handle: FlatHandle, angvel: &RawVector, wakeUp: bool) {
+ self.map_mut(handle, |rb| {
+ rb.set_angvel(angvel.0, wakeUp);
+ });
+ }
+
+ /// If this rigid body is kinematic, sets its future translation after the next timestep integration.
+ ///
+ /// This should be used instead of `rigidBody.setTranslation` to make the dynamic object
+ /// interacting with this kinematic body behave as expected. Internally, Rapier will compute
+ /// an artificial velocity for this rigid-body from its current position and its next kinematic
+ /// position. This velocity will be used to compute forces on dynamic bodies interacting with
+ /// this body.
+ ///
+ /// # Parameters
+ /// - `x`: the world-space position of the rigid-body along the `x` axis.
+ /// - `y`: the world-space position of the rigid-body along the `y` axis.
+ /// - `z`: the world-space position of the rigid-body along the `z` axis.
+ #[cfg(feature = "dim3")]
+ pub fn rbSetNextKinematicTranslation(&mut self, handle: FlatHandle, x: f32, y: f32, z: f32) {
+ self.map_mut(handle, |rb| {
+ rb.set_next_kinematic_translation(Vector::new(x, y, z));
+ })
+ }
+
+ /// If this rigid body is kinematic, sets its future translation after the next timestep integration.
+ ///
+ /// This should be used instead of `rigidBody.setTranslation` to make the dynamic object
+ /// interacting with this kinematic body behave as expected. Internally, Rapier will compute
+ /// an artificial velocity for this rigid-body from its current position and its next kinematic
+ /// position. This velocity will be used to compute forces on dynamic bodies interacting with
+ /// this body.
+ ///
+ /// # Parameters
+ /// - `x`: the world-space position of the rigid-body along the `x` axis.
+ /// - `y`: the world-space position of the rigid-body along the `y` axis.
+ #[cfg(feature = "dim2")]
+ pub fn rbSetNextKinematicTranslation(&mut self, handle: FlatHandle, x: f32, y: f32) {
+ self.map_mut(handle, |rb| {
+ rb.set_next_kinematic_translation(Vector::new(x, y));
+ })
+ }
+
+ /// If this rigid body is kinematic, sets its future rotation after the next timestep integration.
+ ///
+ /// This should be used instead of `rigidBody.setRotation` to make the dynamic object
+ /// interacting with this kinematic body behave as expected. Internally, Rapier will compute
+ /// an artificial velocity for this rigid-body from its current position and its next kinematic
+ /// position. This velocity will be used to compute forces on dynamic bodies interacting with
+ /// this body.
+ ///
+ /// # Parameters
+ /// - `x`: the first vector component of the quaternion.
+ /// - `y`: the second vector component of the quaternion.
+ /// - `z`: the third vector component of the quaternion.
+ /// - `w`: the scalar component of the quaternion.
+ #[cfg(feature = "dim3")]
+ pub fn rbSetNextKinematicRotation(
+ &mut self,
+ handle: FlatHandle,
+ x: f32,
+ y: f32,
+ z: f32,
+ w: f32,
+ ) {
+ let q = Rotation::from_xyzw(x, y, z, w);
+ if q.length_squared() > 0.0 {
+ let q = q.normalize();
+ self.map_mut(handle, |rb| {
+ rb.set_next_kinematic_rotation(q);
+ })
+ }
+ }
+
+ /// If this rigid body is kinematic, sets its future rotation after the next timestep integration.
+ ///
+ /// This should be used instead of `rigidBody.setRotation` to make the dynamic object
+ /// interacting with this kinematic body behave as expected. Internally, Rapier will compute
+ /// an artificial velocity for this rigid-body from its current position and its next kinematic
+ /// position. This velocity will be used to compute forces on dynamic bodies interacting with
+ /// this body.
+ ///
+ /// # Parameters
+ /// - `angle`: the rotation angle, in radians.
+ #[cfg(feature = "dim2")]
+ pub fn rbSetNextKinematicRotation(&mut self, handle: FlatHandle, angle: f32) {
+ self.map_mut(handle, |rb| {
+ rb.set_next_kinematic_rotation(Rotation::new(angle));
+ })
+ }
+
+ pub fn rbRecomputeMassPropertiesFromColliders(
+ &mut self,
+ handle: FlatHandle,
+ colliders: &RawColliderSet,
+ ) {
+ self.map_mut(handle, |rb| {
+ rb.recompute_mass_properties_from_colliders(&colliders.0)
+ })
+ }
+
+ pub fn rbSetAdditionalMass(&mut self, handle: FlatHandle, mass: f32, wake_up: bool) {
+ self.map_mut(handle, |rb| {
+ rb.set_additional_mass(mass, wake_up);
+ })
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn rbSetAdditionalMassProperties(
+ &mut self,
+ handle: FlatHandle,
+ mass: f32,
+ centerOfMass: &RawVector,
+ principalAngularInertia: &RawVector,
+ angularInertiaFrame: &RawRotation,
+ wake_up: bool,
+ ) {
+ self.map_mut(handle, |rb| {
+ let mprops = MassProperties::with_principal_inertia_frame(
+ centerOfMass.0.into(),
+ mass,
+ principalAngularInertia.0,
+ angularInertiaFrame.0,
+ );
+ rb.set_additional_mass_properties(mprops, wake_up)
+ })
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn rbSetAdditionalMassProperties(
+ &mut self,
+ handle: FlatHandle,
+ mass: f32,
+ centerOfMass: &RawVector,
+ principalAngularInertia: f32,
+ wake_up: bool,
+ ) {
+ self.map_mut(handle, |rb| {
+ let props = MassProperties::new(centerOfMass.0.into(), mass, principalAngularInertia);
+ rb.set_additional_mass_properties(props, wake_up)
+ })
+ }
+
+ /// The linear velocity of this rigid-body.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim2")]
+ pub fn rbLinvel(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) {
+ self.map(handle, |rb| {
+ let u = rb.linvel();
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ });
+ }
+
+ /// The linear velocity of this rigid-body.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim3")]
+ pub fn rbLinvel(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) {
+ self.map(handle, |rb| {
+ let u = rb.linvel();
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ });
+ }
+
+ /// The angular velocity of this rigid-body.
+ #[cfg(feature = "dim2")]
+ pub fn rbAngvel(&self, handle: FlatHandle) -> f32 {
+ self.map(handle, |rb| rb.angvel())
+ }
+
+ /// The angular velocity of this rigid-body.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim3")]
+ pub fn rbAngvel(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) {
+ self.map(handle, |rb| {
+ let u = rb.angvel();
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ });
+ }
+
+ /// The velocity of the given world-space point on this rigid-body.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim2")]
+ pub fn rbVelocityAtPoint(
+ &self,
+ handle: FlatHandle,
+ point: &RawVector,
+ scratch_buffer: &js_sys::Float32Array,
+ ) {
+ self.map(handle, |rb| {
+ let u = rb.velocity_at_point(point.0);
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ });
+ }
+
+ /// The velocity of the given world-space point on this rigid-body.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim3")]
+ pub fn rbVelocityAtPoint(
+ &self,
+ handle: FlatHandle,
+ point: &RawVector,
+ scratch_buffer: &js_sys::Float32Array,
+ ) {
+ self.map(handle, |rb| {
+ let u = rb.velocity_at_point(point.0);
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ });
+ }
+
+ pub fn rbLockTranslations(&mut self, handle: FlatHandle, locked: bool, wake_up: bool) {
+ self.map_mut(handle, |rb| rb.lock_translations(locked, wake_up))
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn rbSetEnabledTranslations(
+ &mut self,
+ handle: FlatHandle,
+ allow_x: bool,
+ allow_y: bool,
+ wake_up: bool,
+ ) {
+ self.map_mut(handle, |rb| {
+ rb.set_enabled_translations(allow_x, allow_y, wake_up)
+ })
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn rbSetEnabledTranslations(
+ &mut self,
+ handle: FlatHandle,
+ allow_x: bool,
+ allow_y: bool,
+ allow_z: bool,
+ wake_up: bool,
+ ) {
+ self.map_mut(handle, |rb| {
+ rb.set_enabled_translations(allow_x, allow_y, allow_z, wake_up)
+ })
+ }
+
+ pub fn rbLockRotations(&mut self, handle: FlatHandle, locked: bool, wake_up: bool) {
+ self.map_mut(handle, |rb| rb.lock_rotations(locked, wake_up))
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn rbSetEnabledRotations(
+ &mut self,
+ handle: FlatHandle,
+ allow_x: bool,
+ allow_y: bool,
+ allow_z: bool,
+ wake_up: bool,
+ ) {
+ self.map_mut(handle, |rb| {
+ rb.set_enabled_rotations(allow_x, allow_y, allow_z, wake_up)
+ })
+ }
+
+ pub fn rbDominanceGroup(&self, handle: FlatHandle) -> i8 {
+ self.map(handle, |rb| rb.dominance_group())
+ }
+
+ pub fn rbSetDominanceGroup(&mut self, handle: FlatHandle, group: i8) {
+ self.map_mut(handle, |rb| rb.set_dominance_group(group))
+ }
+
+ pub fn rbEnableCcd(&mut self, handle: FlatHandle, enabled: bool) {
+ self.map_mut(handle, |rb| rb.enable_ccd(enabled))
+ }
+
+ pub fn rbSetSoftCcdPrediction(&mut self, handle: FlatHandle, prediction: f32) {
+ self.map_mut(handle, |rb| rb.set_soft_ccd_prediction(prediction))
+ }
+
+ /// The mass of this rigid-body.
+ pub fn rbMass(&self, handle: FlatHandle) -> f32 {
+ self.map(handle, |rb| rb.mass())
+ }
+
+ /// The inverse of the mass of a rigid-body.
+ ///
+ /// If this is zero, the rigid-body is assumed to have infinite mass.
+ pub fn rbInvMass(&self, handle: FlatHandle) -> f32 {
+ self.map(handle, |rb| rb.mass_properties().local_mprops.inv_mass)
+ }
+
+ /// The inverse mass taking into account translation locking.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim2")]
+ pub fn rbEffectiveInvMass(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) {
+ self.map(handle, |rb| {
+ let u = rb.mass_properties().effective_inv_mass;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ });
+ }
+
+ /// The inverse mass taking into account translation locking.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim3")]
+ pub fn rbEffectiveInvMass(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) {
+ self.map(handle, |rb| {
+ let u = rb.mass_properties().effective_inv_mass;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ });
+ }
+
+ /// The center of mass of a rigid-body expressed in its local-space.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim2")]
+ pub fn rbLocalCom(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) {
+ self.map(handle, |rb| {
+ let u = rb.mass_properties().local_mprops.local_com;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ });
+ }
+
+ /// The center of mass of a rigid-body expressed in its local-space.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim3")]
+ pub fn rbLocalCom(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) {
+ self.map(handle, |rb| {
+ let u = rb.mass_properties().local_mprops.local_com;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ });
+ }
+
+ /// The world-space center of mass of the rigid-body.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim2")]
+ pub fn rbWorldCom(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) {
+ self.map(handle, |rb| {
+ let u = rb.mass_properties().world_com;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ });
+ }
+
+ /// The world-space center of mass of the rigid-body.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim3")]
+ pub fn rbWorldCom(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) {
+ self.map(handle, |rb| {
+ let u = rb.mass_properties().world_com;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ });
+ }
+
+ /// The inverse of the principal angular inertia of the rigid-body.
+ ///
+ /// Components set to zero are assumed to be infinite along the corresponding principal axis.
+ #[cfg(feature = "dim2")]
+ pub fn rbInvPrincipalInertia(&self, handle: FlatHandle) -> f32 {
+ self.map(handle, |rb| {
+ rb.mass_properties().local_mprops.inv_principal_inertia
+ })
+ }
+
+ /// The inverse of the principal angular inertia of the rigid-body.
+ ///
+ /// Components set to zero are assumed to be infinite along the corresponding principal axis.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim3")]
+ pub fn rbInvPrincipalInertia(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) {
+ self.map(handle, |rb| {
+ let u = rb.mass_properties().local_mprops.inv_principal_inertia;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ });
+ }
+
+ /// The principal vectors of the local angular inertia tensor of the rigid-body.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim3")]
+ pub fn rbPrincipalInertiaLocalFrame(
+ &self,
+ handle: FlatHandle,
+ scratch_buffer: &js_sys::Float32Array,
+ ) {
+ self.map(handle, |rb| {
+ let u = rb
+ .mass_properties()
+ .local_mprops
+ .principal_inertia_local_frame;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ scratch_buffer.set_index(3, u.w);
+ });
+ }
+
+ /// The angular inertia along the principal inertia axes of the rigid-body.
+ #[cfg(feature = "dim2")]
+ pub fn rbPrincipalInertia(&self, handle: FlatHandle) -> f32 {
+ self.map(handle, |rb| {
+ rb.mass_properties().local_mprops.principal_inertia()
+ })
+ }
+
+ /// The angular inertia along the principal inertia axes of the rigid-body.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim3")]
+ pub fn rbPrincipalInertia(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) {
+ self.map(handle, |rb| {
+ let u = rb.mass_properties().local_mprops.principal_inertia();
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ });
+ }
+
+ /// The world-space inverse angular inertia tensor of the rigid-body,
+ /// taking into account rotation locking.
+ #[cfg(feature = "dim2")]
+ pub fn rbEffectiveWorldInvInertia(&self, handle: FlatHandle) -> f32 {
+ self.map(handle, |rb| {
+ rb.mass_properties().effective_world_inv_inertia
+ })
+ }
+
+ /// The world-space inverse angular inertia tensor of the rigid-body,
+ /// taking into account rotation locking.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim3")]
+ pub fn rbEffectiveWorldInvInertia(
+ &self,
+ handle: FlatHandle,
+ scratch_buffer: &js_sys::Float32Array,
+ ) {
+ self.map(handle, |rb| {
+ let u = rb.mass_properties().effective_world_inv_inertia;
+ scratch_buffer.set_index(0, u.m11);
+ scratch_buffer.set_index(1, u.m12);
+ scratch_buffer.set_index(2, u.m13);
+ scratch_buffer.set_index(3, u.m22);
+ scratch_buffer.set_index(4, u.m23);
+ scratch_buffer.set_index(5, u.m33);
+ });
+ }
+
+ /// The effective world-space angular inertia (that takes the potential rotation locking into account) of
+ /// this rigid-body.
+ #[cfg(feature = "dim2")]
+ pub fn rbEffectiveAngularInertia(&self, handle: FlatHandle) -> f32 {
+ self.map(handle, |rb| {
+ rb.mass_properties().effective_angular_inertia()
+ })
+ }
+
+ /// The effective world-space angular inertia (that takes the potential rotation locking into account) of
+ /// this rigid-body.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim3")]
+ pub fn rbEffectiveAngularInertia(
+ &self,
+ handle: FlatHandle,
+ scratch_buffer: &js_sys::Float32Array,
+ ) {
+ self.map(handle, |rb| {
+ let u = rb.mass_properties().effective_angular_inertia();
+ scratch_buffer.set_index(0, u.m11);
+ scratch_buffer.set_index(1, u.m12);
+ scratch_buffer.set_index(2, u.m13);
+ scratch_buffer.set_index(3, u.m22);
+ scratch_buffer.set_index(4, u.m23);
+ scratch_buffer.set_index(5, u.m33);
+ });
+ }
+
+ /// Wakes this rigid-body up.
+ ///
+ /// A dynamic rigid-body that does not move during several consecutive frames will
+ /// be put to sleep by the physics engine, i.e., it will stop being simulated in order
+ /// to avoid useless computations.
+ /// This method forces a sleeping rigid-body to wake-up. This is useful, e.g., before modifying
+ /// the position of a dynamic body so that it is properly simulated afterwards.
+ pub fn rbWakeUp(&mut self, handle: FlatHandle) {
+ self.map_mut(handle, |rb| rb.wake_up(true))
+ }
+
+ /// Is Continuous Collision Detection enabled for this rigid-body?
+ pub fn rbIsCcdEnabled(&self, handle: FlatHandle) -> bool {
+ self.map(handle, |rb| rb.is_ccd_enabled())
+ }
+ pub fn rbSoftCcdPrediction(&self, handle: FlatHandle) -> f32 {
+ self.map(handle, |rb| rb.soft_ccd_prediction())
+ }
+
+ /// The number of colliders attached to this rigid-body.
+ pub fn rbNumColliders(&self, handle: FlatHandle) -> usize {
+ self.map(handle, |rb| rb.colliders().len())
+ }
+
+ /// Retrieves the `i-th` collider attached to this rigid-body.
+ ///
+ /// # Parameters
+ /// - `at`: The index of the collider to retrieve. Must be a number in `[0, this.numColliders()[`.
+ /// This index is **not** the same as the unique identifier of the collider.
+ pub fn rbCollider(&self, handle: FlatHandle, at: usize) -> FlatHandle {
+ self.map(handle, |rb| utils::flat_handle(rb.colliders()[at].0))
+ }
+
+ /// The status of this rigid-body: fixed, dynamic, or kinematic.
+ pub fn rbBodyType(&self, handle: FlatHandle) -> RawRigidBodyType {
+ self.map(handle, |rb| rb.body_type().into())
+ }
+
+ /// Set a new status for this rigid-body: fixed, dynamic, or kinematic.
+ pub fn rbSetBodyType(&mut self, handle: FlatHandle, status: RawRigidBodyType, wake_up: bool) {
+ self.map_mut(handle, |rb| rb.set_body_type(status.into(), wake_up));
+ }
+
+ /// Is this rigid-body fixed?
+ pub fn rbIsFixed(&self, handle: FlatHandle) -> bool {
+ self.map(handle, |rb| rb.is_fixed())
+ }
+
+ /// Is this rigid-body kinematic?
+ pub fn rbIsKinematic(&self, handle: FlatHandle) -> bool {
+ self.map(handle, |rb| rb.is_kinematic())
+ }
+
+ /// Is this rigid-body dynamic?
+ pub fn rbIsDynamic(&self, handle: FlatHandle) -> bool {
+ self.map(handle, |rb| rb.is_dynamic())
+ }
+
+ /// The linear damping coefficient of this rigid-body.
+ pub fn rbLinearDamping(&self, handle: FlatHandle) -> f32 {
+ self.map(handle, |rb| rb.linear_damping())
+ }
+
+ /// The angular damping coefficient of this rigid-body.
+ pub fn rbAngularDamping(&self, handle: FlatHandle) -> f32 {
+ self.map(handle, |rb| rb.angular_damping())
+ }
+
+ pub fn rbSetLinearDamping(&mut self, handle: FlatHandle, factor: f32) {
+ self.map_mut(handle, |rb| rb.set_linear_damping(factor));
+ }
+
+ pub fn rbSetAngularDamping(&mut self, handle: FlatHandle, factor: f32) {
+ self.map_mut(handle, |rb| rb.set_angular_damping(factor));
+ }
+
+ pub fn rbSetEnabled(&mut self, handle: FlatHandle, enabled: bool) {
+ self.map_mut(handle, |rb| rb.set_enabled(enabled))
+ }
+
+ pub fn rbIsEnabled(&self, handle: FlatHandle) -> bool {
+ self.map(handle, |rb| rb.is_enabled())
+ }
+
+ pub fn rbGravityScale(&self, handle: FlatHandle) -> f32 {
+ self.map(handle, |rb| rb.gravity_scale())
+ }
+
+ pub fn rbSetGravityScale(&mut self, handle: FlatHandle, factor: f32, wakeUp: bool) {
+ self.map_mut(handle, |rb| rb.set_gravity_scale(factor, wakeUp));
+ }
+
+ /// Resets to zero all user-added forces added to this rigid-body.
+ pub fn rbResetForces(&mut self, handle: FlatHandle, wakeUp: bool) {
+ self.map_mut(handle, |rb| {
+ rb.reset_forces(wakeUp);
+ })
+ }
+
+ /// Resets to zero all user-added torques added to this rigid-body.
+ pub fn rbResetTorques(&mut self, handle: FlatHandle, wakeUp: bool) {
+ self.map_mut(handle, |rb| {
+ rb.reset_torques(wakeUp);
+ })
+ }
+
+ /// Adds a force at the center-of-mass of this rigid-body.
+ ///
+ /// # Parameters
+ /// - `force`: the world-space force to apply on the rigid-body.
+ /// - `wakeUp`: should the rigid-body be automatically woken-up?
+ pub fn rbAddForce(&mut self, handle: FlatHandle, force: &RawVector, wakeUp: bool) {
+ self.map_mut(handle, |rb| {
+ rb.add_force(force.0, wakeUp);
+ })
+ }
+
+ /// Applies an impulse at the center-of-mass of this rigid-body.
+ ///
+ /// # Parameters
+ /// - `impulse`: the world-space impulse to apply on the rigid-body.
+ /// - `wakeUp`: should the rigid-body be automatically woken-up?
+ pub fn rbApplyImpulse(&mut self, handle: FlatHandle, impulse: &RawVector, wakeUp: bool) {
+ self.map_mut(handle, |rb| {
+ rb.apply_impulse(impulse.0, wakeUp);
+ })
+ }
+
+ /// Adds a torque at the center-of-mass of this rigid-body.
+ ///
+ /// # Parameters
+ /// - `torque`: the torque to apply on the rigid-body.
+ /// - `wakeUp`: should the rigid-body be automatically woken-up?
+ #[cfg(feature = "dim2")]
+ pub fn rbAddTorque(&mut self, handle: FlatHandle, torque: f32, wakeUp: bool) {
+ self.map_mut(handle, |rb| {
+ rb.add_torque(torque, wakeUp);
+ })
+ }
+
+ /// Adds a torque at the center-of-mass of this rigid-body.
+ ///
+ /// # Parameters
+ /// - `torque`: the world-space torque to apply on the rigid-body.
+ /// - `wakeUp`: should the rigid-body be automatically woken-up?
+ #[cfg(feature = "dim3")]
+ pub fn rbAddTorque(&mut self, handle: FlatHandle, torque: &RawVector, wakeUp: bool) {
+ self.map_mut(handle, |rb| {
+ rb.add_torque(torque.0, wakeUp);
+ })
+ }
+
+ /// Applies an impulsive torque at the center-of-mass of this rigid-body.
+ ///
+ /// # Parameters
+ /// - `torque impulse`: the torque impulse to apply on the rigid-body.
+ /// - `wakeUp`: should the rigid-body be automatically woken-up?
+ #[cfg(feature = "dim2")]
+ pub fn rbApplyTorqueImpulse(&mut self, handle: FlatHandle, torque_impulse: f32, wakeUp: bool) {
+ self.map_mut(handle, |rb| {
+ rb.apply_torque_impulse(torque_impulse, wakeUp);
+ })
+ }
+
+ /// Applies an impulsive torque at the center-of-mass of this rigid-body.
+ ///
+ /// # Parameters
+ /// - `torque impulse`: the world-space torque impulse to apply on the rigid-body.
+ /// - `wakeUp`: should the rigid-body be automatically woken-up?
+ #[cfg(feature = "dim3")]
+ pub fn rbApplyTorqueImpulse(
+ &mut self,
+ handle: FlatHandle,
+ torque_impulse: &RawVector,
+ wakeUp: bool,
+ ) {
+ self.map_mut(handle, |rb| {
+ rb.apply_torque_impulse(torque_impulse.0, wakeUp);
+ })
+ }
+
+ /// Adds a force at the given world-space point of this rigid-body.
+ ///
+ /// # Parameters
+ /// - `force`: the world-space force to apply on the rigid-body.
+ /// - `point`: the world-space point where the impulse is to be applied on the rigid-body.
+ /// - `wakeUp`: should the rigid-body be automatically woken-up?
+ pub fn rbAddForceAtPoint(
+ &mut self,
+ handle: FlatHandle,
+ force: &RawVector,
+ point: &RawVector,
+ wakeUp: bool,
+ ) {
+ self.map_mut(handle, |rb| {
+ rb.add_force_at_point(force.0, point.0.into(), wakeUp);
+ })
+ }
+
+ /// Applies an impulse at the given world-space point of this rigid-body.
+ ///
+ /// # Parameters
+ /// - `impulse`: the world-space impulse to apply on the rigid-body.
+ /// - `point`: the world-space point where the impulse is to be applied on the rigid-body.
+ /// - `wakeUp`: should the rigid-body be automatically woken-up?
+ pub fn rbApplyImpulseAtPoint(
+ &mut self,
+ handle: FlatHandle,
+ impulse: &RawVector,
+ point: &RawVector,
+ wakeUp: bool,
+ ) {
+ self.map_mut(handle, |rb| {
+ rb.apply_impulse_at_point(impulse.0, point.0.into(), wakeUp);
+ })
+ }
+
+ pub fn rbAdditionalSolverIterations(&self, handle: FlatHandle) -> usize {
+ self.map(handle, |rb| rb.additional_solver_iterations())
+ }
+
+ pub fn rbSetAdditionalSolverIterations(&mut self, handle: FlatHandle, iters: usize) {
+ self.map_mut(handle, |rb| {
+ rb.set_additional_solver_iterations(iters as usize);
+ })
+ }
+
+ /// An arbitrary user-defined 32-bit integer
+ pub fn rbUserData(&self, handle: FlatHandle) -> u32 {
+ self.map(handle, |rb| rb.user_data as u32)
+ }
+
+ /// Sets the user-defined 32-bit integer of this rigid-body.
+ ///
+ /// # Parameters
+ /// - `data`: an arbitrary user-defined 32-bit integer.
+ pub fn rbSetUserData(&mut self, handle: FlatHandle, data: u32) {
+ self.map_mut(handle, |rb| {
+ rb.user_data = data as u128;
+ })
+ }
+
+ /// Retrieves the constant force(s) the user added to this rigid-body.
+ /// Returns zero if the rigid-body is not dynamic.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim2")]
+ pub fn rbUserForce(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) {
+ self.map(handle, |rb| {
+ let u = rb.user_force();
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ });
+ }
+
+ /// Retrieves the constant force(s) the user added to this rigid-body.
+ /// Returns zero if the rigid-body is not dynamic.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim3")]
+ pub fn rbUserForce(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) {
+ self.map(handle, |rb| {
+ let u = rb.user_force();
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ });
+ }
+
+ /// Retrieves the constant torque(s) the user added to this rigid-body.
+ /// Returns zero if the rigid-body is not dynamic.
+ #[cfg(feature = "dim2")]
+ pub fn rbUserTorque(&self, handle: FlatHandle) -> f32 {
+ self.map(handle, |rb| rb.user_torque())
+ }
+
+ /// Retrieves the constant torque(s) the user added to this rigid-body.
+ /// Returns zero if the rigid-body is not dynamic.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim3")]
+ pub fn rbUserTorque(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) {
+ self.map(handle, |rb| {
+ let u = rb.user_torque();
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ });
+ }
+}
diff --git a/typescript/src/dynamics/rigid_body_set.rs b/typescript/src/dynamics/rigid_body_set.rs
new file mode 100644
index 000000000..d8027c72c
--- /dev/null
+++ b/typescript/src/dynamics/rigid_body_set.rs
@@ -0,0 +1,238 @@
+use crate::dynamics::{RawImpulseJointSet, RawIslandManager, RawMultibodyJointSet};
+use crate::geometry::RawColliderSet;
+use crate::math::{RawRotation, RawVector};
+use crate::utils::{self, FlatHandle};
+use rapier::dynamics::{MassProperties, RigidBody, RigidBodyBuilder, RigidBodySet, RigidBodyType};
+use rapier::math::Pose;
+use wasm_bindgen::prelude::*;
+
+#[wasm_bindgen]
+pub enum RawRigidBodyType {
+ Dynamic,
+ Fixed,
+ KinematicPositionBased,
+ KinematicVelocityBased,
+}
+
+impl Into for RawRigidBodyType {
+ fn into(self) -> RigidBodyType {
+ match self {
+ RawRigidBodyType::Dynamic => RigidBodyType::Dynamic,
+ RawRigidBodyType::Fixed => RigidBodyType::Fixed,
+ RawRigidBodyType::KinematicPositionBased => RigidBodyType::KinematicPositionBased,
+ RawRigidBodyType::KinematicVelocityBased => RigidBodyType::KinematicVelocityBased,
+ }
+ }
+}
+
+impl Into for RigidBodyType {
+ fn into(self) -> RawRigidBodyType {
+ match self {
+ RigidBodyType::Dynamic => RawRigidBodyType::Dynamic,
+ RigidBodyType::Fixed => RawRigidBodyType::Fixed,
+ RigidBodyType::KinematicPositionBased => RawRigidBodyType::KinematicPositionBased,
+ RigidBodyType::KinematicVelocityBased => RawRigidBodyType::KinematicVelocityBased,
+ }
+ }
+}
+
+#[wasm_bindgen]
+pub struct RawRigidBodySet(pub(crate) RigidBodySet);
+
+impl RawRigidBodySet {
+ pub(crate) fn map(&self, handle: FlatHandle, f: impl FnOnce(&RigidBody) -> T) -> T {
+ let body = self.0.get(utils::body_handle(handle)).expect(
+ "Invalid RigidBody reference. It may have been removed from the physics World.",
+ );
+ f(body)
+ }
+
+ pub(crate) fn map_mut(
+ &mut self,
+ handle: FlatHandle,
+ f: impl FnOnce(&mut RigidBody) -> T,
+ ) -> T {
+ let body = self.0.get_mut(utils::body_handle(handle)).expect(
+ "Invalid RigidBody reference. It may have been removed from the physics World.",
+ );
+ f(body)
+ }
+}
+
+#[wasm_bindgen]
+impl RawRigidBodySet {
+ #[wasm_bindgen(constructor)]
+ pub fn new() -> Self {
+ RawRigidBodySet(RigidBodySet::new())
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn createRigidBody(
+ &mut self,
+ enabled: bool,
+ translation: &RawVector,
+ rotation: &RawRotation,
+ gravityScale: f32,
+ mass: f32,
+ massOnly: bool,
+ centerOfMass: &RawVector,
+ linvel: &RawVector,
+ angvel: &RawVector,
+ principalAngularInertia: &RawVector,
+ angularInertiaFrame: &RawRotation,
+ translationEnabledX: bool,
+ translationEnabledY: bool,
+ translationEnabledZ: bool,
+ rotationEnabledX: bool,
+ rotationEnabledY: bool,
+ rotationEnabledZ: bool,
+ linearDamping: f32,
+ angularDamping: f32,
+ rb_type: RawRigidBodyType,
+ canSleep: bool,
+ sleeping: bool,
+ softCcdPrediction: f32,
+ ccdEnabled: bool,
+ dominanceGroup: i8,
+ additional_solver_iterations: usize,
+ ) -> FlatHandle {
+ let pos = Pose::from_parts(translation.0, rotation.0);
+
+ let mut rigid_body = RigidBodyBuilder::new(rb_type.into())
+ .enabled(enabled)
+ .pose(pos)
+ .gravity_scale(gravityScale)
+ .enabled_translations(
+ translationEnabledX,
+ translationEnabledY,
+ translationEnabledZ,
+ )
+ .enabled_rotations(rotationEnabledX, rotationEnabledY, rotationEnabledZ)
+ .linvel(linvel.0)
+ .angvel(angvel.0)
+ .linear_damping(linearDamping)
+ .angular_damping(angularDamping)
+ .can_sleep(canSleep)
+ .sleeping(sleeping)
+ .ccd_enabled(ccdEnabled)
+ .dominance_group(dominanceGroup)
+ .additional_solver_iterations(additional_solver_iterations)
+ .soft_ccd_prediction(softCcdPrediction);
+
+ rigid_body = if massOnly {
+ rigid_body.additional_mass(mass)
+ } else {
+ let props = MassProperties::with_principal_inertia_frame(
+ centerOfMass.0.into(),
+ mass,
+ principalAngularInertia.0,
+ angularInertiaFrame.0,
+ );
+ rigid_body.additional_mass_properties(props)
+ };
+
+ utils::flat_handle(self.0.insert(rigid_body.build()).0)
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn createRigidBody(
+ &mut self,
+ enabled: bool,
+ translation: &RawVector,
+ rotation: &RawRotation,
+ gravityScale: f32,
+ mass: f32,
+ massOnly: bool,
+ centerOfMass: &RawVector,
+ linvel: &RawVector,
+ angvel: f32,
+ principalAngularInertia: f32,
+ translationEnabledX: bool,
+ translationEnabledY: bool,
+ rotationsEnabled: bool,
+ linearDamping: f32,
+ angularDamping: f32,
+ rb_type: RawRigidBodyType,
+ canSleep: bool,
+ sleeping: bool,
+ softCcdPrediction: f32,
+ ccdEnabled: bool,
+ dominanceGroup: i8,
+ additional_solver_iterations: usize,
+ ) -> FlatHandle {
+ let pos = Pose::from_parts(translation.0, rotation.0);
+ let mut rigid_body = RigidBodyBuilder::new(rb_type.into())
+ .enabled(enabled)
+ .pose(pos)
+ .gravity_scale(gravityScale)
+ .enabled_translations(translationEnabledX, translationEnabledY)
+ .linvel(linvel.0)
+ .angvel(angvel)
+ .linear_damping(linearDamping)
+ .angular_damping(angularDamping)
+ .can_sleep(canSleep)
+ .sleeping(sleeping)
+ .ccd_enabled(ccdEnabled)
+ .dominance_group(dominanceGroup)
+ .additional_solver_iterations(additional_solver_iterations)
+ .soft_ccd_prediction(softCcdPrediction);
+
+ rigid_body = if massOnly {
+ rigid_body.additional_mass(mass)
+ } else {
+ let props = MassProperties::new(centerOfMass.0.into(), mass, principalAngularInertia);
+ rigid_body.additional_mass_properties(props)
+ };
+
+ if !rotationsEnabled {
+ rigid_body = rigid_body.lock_rotations();
+ }
+
+ utils::flat_handle(self.0.insert(rigid_body.build()).0)
+ }
+
+ pub fn remove(
+ &mut self,
+ handle: FlatHandle,
+ islands: &mut RawIslandManager,
+ colliders: &mut RawColliderSet,
+ joints: &mut RawImpulseJointSet,
+ articulations: &mut RawMultibodyJointSet,
+ ) {
+ let handle = utils::body_handle(handle);
+ self.0.remove(
+ handle,
+ &mut islands.0,
+ &mut colliders.0,
+ &mut joints.0,
+ &mut articulations.0,
+ true,
+ );
+ }
+
+ /// The number of rigid-bodies on this set.
+ pub fn len(&self) -> usize {
+ self.0.len()
+ }
+
+ /// Checks if a rigid-body with the given integer handle exists.
+ pub fn contains(&self, handle: FlatHandle) -> bool {
+ self.0.get(utils::body_handle(handle)).is_some()
+ }
+
+ /// Applies the given JavaScript function to the integer handle of each rigid-body managed by this set.
+ ///
+ /// # Parameters
+ /// - `f(handle)`: the function to apply to the integer handle of each rigid-body managed by this set. Called as `f(collider)`.
+ pub fn forEachRigidBodyHandle(&self, f: &js_sys::Function) {
+ let this = JsValue::null();
+ for (handle, _) in self.0.iter() {
+ let _ = f.call1(&this, &JsValue::from(utils::flat_handle(handle.0)));
+ }
+ }
+
+ pub fn propagateModifiedBodyPositionsToColliders(&mut self, colliders: &mut RawColliderSet) {
+ self.0
+ .propagate_modified_body_positions_to_colliders(&mut colliders.0);
+ }
+}
diff --git a/typescript/src/geometry/broad_phase.rs b/typescript/src/geometry/broad_phase.rs
new file mode 100644
index 000000000..f85a7762e
--- /dev/null
+++ b/typescript/src/geometry/broad_phase.rs
@@ -0,0 +1,462 @@
+use crate::dynamics::RawRigidBodySet;
+use crate::geometry::{
+ RawColliderSet, RawColliderShapeCastHit, RawNarrowPhase, RawPointColliderProjection,
+ RawRayColliderHit, RawRayColliderIntersection, RawShape,
+};
+use crate::math::{RawRotation, RawVector};
+use crate::utils::{self, FlatHandle};
+use rapier::geometry::DefaultBroadPhase;
+use rapier::geometry::{Aabb, ColliderHandle, Ray};
+use rapier::math::Pose;
+use rapier::parry::query::ShapeCastOptions;
+use rapier::pipeline::{QueryFilter, QueryFilterFlags};
+use rapier::prelude::FeatureId;
+use wasm_bindgen::prelude::*;
+
+#[wasm_bindgen]
+pub struct RawBroadPhase(pub(crate) DefaultBroadPhase);
+
+#[wasm_bindgen]
+impl RawBroadPhase {
+ #[wasm_bindgen(constructor)]
+ pub fn new() -> Self {
+ RawBroadPhase(DefaultBroadPhase::new())
+ }
+
+ pub fn castRay(
+ &self,
+ narrow_phase: &RawNarrowPhase,
+ bodies: &RawRigidBodySet,
+ colliders: &RawColliderSet,
+ rayOrig: &RawVector,
+ rayDir: &RawVector,
+ maxToi: f32,
+ solid: bool,
+ filter_flags: u32,
+ filter_groups: Option,
+ filter_exclude_collider: Option,
+ filter_exclude_rigid_body: Option,
+ filter_predicate: &js_sys::Function,
+ ) -> Option {
+ let (handle, timeOfImpact) = utils::with_filter(filter_predicate, |predicate| {
+ let query_filter = QueryFilter {
+ flags: QueryFilterFlags::from_bits(filter_flags)
+ .unwrap_or(QueryFilterFlags::empty()),
+ groups: filter_groups.map(crate::geometry::unpack_interaction_groups),
+ exclude_collider: filter_exclude_collider.map(crate::utils::collider_handle),
+ exclude_rigid_body: filter_exclude_rigid_body.map(crate::utils::body_handle),
+ predicate,
+ };
+
+ let query_pipeline = self.0.as_query_pipeline(
+ narrow_phase.0.query_dispatcher(),
+ &bodies.0,
+ &colliders.0,
+ query_filter,
+ );
+
+ let ray = Ray::new(rayOrig.0, rayDir.0);
+ query_pipeline.cast_ray(&ray, maxToi, solid)
+ })?;
+
+ Some(RawRayColliderHit {
+ handle,
+ timeOfImpact,
+ })
+ }
+
+ pub fn castRayAndGetNormal(
+ &self,
+ narrow_phase: &RawNarrowPhase,
+ bodies: &RawRigidBodySet,
+ colliders: &RawColliderSet,
+ rayOrig: &RawVector,
+ rayDir: &RawVector,
+ maxToi: f32,
+ solid: bool,
+ filter_flags: u32,
+ filter_groups: Option,
+ filter_exclude_collider: Option,
+ filter_exclude_rigid_body: Option,
+ filter_predicate: &js_sys::Function,
+ ) -> Option {
+ let (handle, inter) = utils::with_filter(filter_predicate, |predicate| {
+ let query_filter = QueryFilter {
+ flags: QueryFilterFlags::from_bits(filter_flags)
+ .unwrap_or(QueryFilterFlags::empty()),
+ groups: filter_groups.map(crate::geometry::unpack_interaction_groups),
+ exclude_collider: filter_exclude_collider.map(crate::utils::collider_handle),
+ exclude_rigid_body: filter_exclude_rigid_body.map(crate::utils::body_handle),
+ predicate,
+ };
+
+ let query_pipeline = self.0.as_query_pipeline(
+ narrow_phase.0.query_dispatcher(),
+ &bodies.0,
+ &colliders.0,
+ query_filter,
+ );
+
+ let ray = Ray::new(rayOrig.0, rayDir.0);
+ query_pipeline.cast_ray_and_get_normal(&ray, maxToi, solid)
+ })?;
+
+ Some(RawRayColliderIntersection { handle, inter })
+ }
+
+ // The callback is of type (RawRayColliderIntersection) => bool
+ pub fn intersectionsWithRay(
+ &self,
+ narrow_phase: &RawNarrowPhase,
+ bodies: &RawRigidBodySet,
+ colliders: &RawColliderSet,
+ rayOrig: &RawVector,
+ rayDir: &RawVector,
+ maxToi: f32,
+ solid: bool,
+ callback: &js_sys::Function,
+ filter_flags: u32,
+ filter_groups: Option,
+ filter_exclude_collider: Option,
+ filter_exclude_rigid_body: Option,
+ filter_predicate: &js_sys::Function,
+ ) {
+ utils::with_filter(filter_predicate, |predicate| {
+ let query_filter = QueryFilter {
+ flags: QueryFilterFlags::from_bits(filter_flags)
+ .unwrap_or(QueryFilterFlags::empty()),
+ groups: filter_groups.map(crate::geometry::unpack_interaction_groups),
+ exclude_collider: filter_exclude_collider.map(crate::utils::collider_handle),
+ exclude_rigid_body: filter_exclude_rigid_body.map(crate::utils::body_handle),
+ predicate,
+ };
+
+ let ray = Ray::new(rayOrig.0, rayDir.0);
+ let rcallback = |handle, inter| {
+ let result = RawRayColliderIntersection { handle, inter };
+ match callback.call1(&JsValue::null(), &JsValue::from(result)) {
+ Err(_) => true,
+ Ok(val) => val.as_bool().unwrap_or(true),
+ }
+ };
+
+ let query_pipeline = self.0.as_query_pipeline(
+ narrow_phase.0.query_dispatcher(),
+ &bodies.0,
+ &colliders.0,
+ query_filter,
+ );
+
+ for (handle, _, inter) in query_pipeline.intersect_ray(ray, maxToi, solid) {
+ if !rcallback(handle, inter) {
+ break;
+ }
+ }
+ });
+ }
+
+ pub fn intersectionWithShape(
+ &self,
+ narrow_phase: &RawNarrowPhase,
+ bodies: &RawRigidBodySet,
+ colliders: &RawColliderSet,
+ shapePos: &RawVector,
+ shapeRot: &RawRotation,
+ shape: &RawShape,
+ filter_flags: u32,
+ filter_groups: Option,
+ filter_exclude_collider: Option,
+ filter_exclude_rigid_body: Option,
+ filter_predicate: &js_sys::Function,
+ ) -> Option {
+ utils::with_filter(filter_predicate, |predicate| {
+ let query_filter = QueryFilter {
+ flags: QueryFilterFlags::from_bits(filter_flags)
+ .unwrap_or(QueryFilterFlags::empty()),
+ groups: filter_groups.map(crate::geometry::unpack_interaction_groups),
+ exclude_collider: filter_exclude_collider.map(crate::utils::collider_handle),
+ exclude_rigid_body: filter_exclude_rigid_body.map(crate::utils::body_handle),
+ predicate,
+ };
+
+ let query_pipeline = self.0.as_query_pipeline(
+ narrow_phase.0.query_dispatcher(),
+ &bodies.0,
+ &colliders.0,
+ query_filter,
+ );
+
+ let pos = Pose::from_parts(shapePos.0.into(), shapeRot.0);
+
+ // TODO: take a callback as argument so we can yield all the intersecting shapes?
+ for (handle, _) in query_pipeline.intersect_shape(pos, &*shape.0) {
+ // Return the first intersection we find.
+ return Some(utils::flat_handle(handle.0));
+ }
+
+ None
+ })
+ }
+
+ pub fn projectPoint(
+ &self,
+ narrow_phase: &RawNarrowPhase,
+ bodies: &RawRigidBodySet,
+ colliders: &RawColliderSet,
+ point: &RawVector,
+ solid: bool,
+ filter_flags: u32,
+ filter_groups: Option,
+ filter_exclude_collider: Option,
+ filter_exclude_rigid_body: Option,
+ filter_predicate: &js_sys::Function,
+ ) -> Option {
+ utils::with_filter(filter_predicate, |predicate| {
+ let query_filter = QueryFilter {
+ flags: QueryFilterFlags::from_bits(filter_flags)
+ .unwrap_or(QueryFilterFlags::empty()),
+ groups: filter_groups.map(crate::geometry::unpack_interaction_groups),
+ exclude_collider: filter_exclude_collider.map(crate::utils::collider_handle),
+ exclude_rigid_body: filter_exclude_rigid_body.map(crate::utils::body_handle),
+ predicate,
+ };
+
+ let query_pipeline = self.0.as_query_pipeline(
+ narrow_phase.0.query_dispatcher(),
+ &bodies.0,
+ &colliders.0,
+ query_filter,
+ );
+
+ query_pipeline
+ .project_point(point.0, f32::MAX, solid)
+ .map(|(handle, proj)| RawPointColliderProjection {
+ handle,
+ proj,
+ feature: FeatureId::Unknown,
+ })
+ })
+ }
+
+ pub fn projectPointAndGetFeature(
+ &self,
+ narrow_phase: &RawNarrowPhase,
+ bodies: &RawRigidBodySet,
+ colliders: &RawColliderSet,
+ point: &RawVector,
+ filter_flags: u32,
+ filter_groups: Option,
+ filter_exclude_collider: Option,
+ filter_exclude_rigid_body: Option,
+ filter_predicate: &js_sys::Function,
+ ) -> Option {
+ utils::with_filter(filter_predicate, |predicate| {
+ let query_filter = QueryFilter {
+ flags: QueryFilterFlags::from_bits(filter_flags)
+ .unwrap_or(QueryFilterFlags::empty()),
+ groups: filter_groups.map(crate::geometry::unpack_interaction_groups),
+ exclude_collider: filter_exclude_collider.map(crate::utils::collider_handle),
+ exclude_rigid_body: filter_exclude_rigid_body.map(crate::utils::body_handle),
+ predicate,
+ };
+
+ let query_pipeline = self.0.as_query_pipeline(
+ narrow_phase.0.query_dispatcher(),
+ &bodies.0,
+ &colliders.0,
+ query_filter,
+ );
+
+ query_pipeline
+ .project_point_and_get_feature(point.0, f32::MAX)
+ .map(|(handle, proj, feature)| RawPointColliderProjection {
+ handle,
+ proj,
+ feature,
+ })
+ })
+ }
+
+ // The callback is of type (u32) => bool
+ pub fn intersectionsWithPoint(
+ &self,
+ narrow_phase: &RawNarrowPhase,
+ bodies: &RawRigidBodySet,
+ colliders: &RawColliderSet,
+ point: &RawVector,
+ callback: &js_sys::Function,
+ filter_flags: u32,
+ filter_groups: Option,
+ filter_exclude_collider: Option,
+ filter_exclude_rigid_body: Option,
+ filter_predicate: &js_sys::Function,
+ ) {
+ utils::with_filter(filter_predicate, |predicate| {
+ let query_filter = QueryFilter {
+ flags: QueryFilterFlags::from_bits(filter_flags)
+ .unwrap_or(QueryFilterFlags::empty()),
+ groups: filter_groups.map(crate::geometry::unpack_interaction_groups),
+ exclude_collider: filter_exclude_collider.map(crate::utils::collider_handle),
+ exclude_rigid_body: filter_exclude_rigid_body.map(crate::utils::body_handle),
+ predicate,
+ };
+
+ let query_pipeline = self.0.as_query_pipeline(
+ narrow_phase.0.query_dispatcher(),
+ &bodies.0,
+ &colliders.0,
+ query_filter,
+ );
+
+ let rcallback = |handle: ColliderHandle| match callback.call1(
+ &JsValue::null(),
+ &JsValue::from(utils::flat_handle(handle.0)),
+ ) {
+ Err(_) => true,
+ Ok(val) => val.as_bool().unwrap_or(true),
+ };
+
+ for (handle, _) in query_pipeline.intersect_point(point.0) {
+ if !rcallback(handle) {
+ break;
+ }
+ }
+ });
+ }
+
+ pub fn castShape(
+ &self,
+ narrow_phase: &RawNarrowPhase,
+ bodies: &RawRigidBodySet,
+ colliders: &RawColliderSet,
+ shapePos: &RawVector,
+ shapeRot: &RawRotation,
+ shapeVel: &RawVector,
+ shape: &RawShape,
+ target_distance: f32,
+ maxToi: f32,
+ stop_at_penetration: bool,
+ filter_flags: u32,
+ filter_groups: Option,
+ filter_exclude_collider: Option,
+ filter_exclude_rigid_body: Option,
+ filter_predicate: &js_sys::Function,
+ ) -> Option {
+ utils::with_filter(filter_predicate, |predicate| {
+ let query_filter = QueryFilter {
+ flags: QueryFilterFlags::from_bits(filter_flags)
+ .unwrap_or(QueryFilterFlags::empty()),
+ groups: filter_groups.map(crate::geometry::unpack_interaction_groups),
+ exclude_collider: filter_exclude_collider.map(crate::utils::collider_handle),
+ exclude_rigid_body: filter_exclude_rigid_body.map(crate::utils::body_handle),
+ predicate,
+ };
+
+ let query_pipeline = self.0.as_query_pipeline(
+ narrow_phase.0.query_dispatcher(),
+ &bodies.0,
+ &colliders.0,
+ query_filter,
+ );
+
+ let pos = Pose::from_parts(shapePos.0.into(), shapeRot.0);
+ query_pipeline
+ .cast_shape(
+ &pos,
+ shapeVel.0,
+ &*shape.0,
+ ShapeCastOptions {
+ max_time_of_impact: maxToi,
+ stop_at_penetration,
+ compute_impact_geometry_on_penetration: true,
+ target_distance,
+ },
+ )
+ .map(|(handle, hit)| RawColliderShapeCastHit { handle, hit })
+ })
+ }
+
+ // The callback has type (u32) => boolean
+ pub fn intersectionsWithShape(
+ &self,
+ narrow_phase: &RawNarrowPhase,
+ bodies: &RawRigidBodySet,
+ colliders: &RawColliderSet,
+ shapePos: &RawVector,
+ shapeRot: &RawRotation,
+ shape: &RawShape,
+ callback: &js_sys::Function,
+ filter_flags: u32,
+ filter_groups: Option,
+ filter_exclude_collider: Option,
+ filter_exclude_rigid_body: Option,
+ filter_predicate: &js_sys::Function,
+ ) {
+ utils::with_filter(filter_predicate, |predicate| {
+ let query_filter = QueryFilter {
+ flags: QueryFilterFlags::from_bits(filter_flags)
+ .unwrap_or(QueryFilterFlags::empty()),
+ groups: filter_groups.map(crate::geometry::unpack_interaction_groups),
+ exclude_collider: filter_exclude_collider.map(crate::utils::collider_handle),
+ exclude_rigid_body: filter_exclude_rigid_body.map(crate::utils::body_handle),
+ predicate,
+ };
+
+ let query_pipeline = self.0.as_query_pipeline(
+ narrow_phase.0.query_dispatcher(),
+ &bodies.0,
+ &colliders.0,
+ query_filter,
+ );
+
+ let rcallback = |handle: ColliderHandle| match callback.call1(
+ &JsValue::null(),
+ &JsValue::from(utils::flat_handle(handle.0)),
+ ) {
+ Err(_) => true,
+ Ok(val) => val.as_bool().unwrap_or(true),
+ };
+
+ let pos = Pose::from_parts(shapePos.0.into(), shapeRot.0);
+ for (handle, _) in query_pipeline.intersect_shape(pos, &*shape.0) {
+ if !rcallback(handle) {
+ break;
+ }
+ }
+ })
+ }
+
+ pub fn collidersWithAabbIntersectingAabb(
+ &self,
+ narrow_phase: &RawNarrowPhase,
+ bodies: &RawRigidBodySet,
+ colliders: &RawColliderSet,
+ aabbCenter: &RawVector,
+ aabbHalfExtents: &RawVector,
+ callback: &js_sys::Function,
+ ) {
+ let rcallback = |handle: &ColliderHandle| match callback.call1(
+ &JsValue::null(),
+ &JsValue::from(utils::flat_handle(handle.0)),
+ ) {
+ Err(_) => true,
+ Ok(val) => val.as_bool().unwrap_or(true),
+ };
+
+ let query_pipeline = self.0.as_query_pipeline(
+ narrow_phase.0.query_dispatcher(),
+ &bodies.0,
+ &colliders.0,
+ Default::default(),
+ );
+
+ let center = aabbCenter.0;
+ let aabb = Aabb::new(center - aabbHalfExtents.0, center + aabbHalfExtents.0);
+
+ for (handle, _) in query_pipeline.intersect_aabb_conservative(aabb) {
+ if !rcallback(&handle) {
+ break;
+ }
+ }
+ }
+}
diff --git a/typescript/src/geometry/collider.rs b/typescript/src/geometry/collider.rs
new file mode 100644
index 000000000..fa68c7d88
--- /dev/null
+++ b/typescript/src/geometry/collider.rs
@@ -0,0 +1,1231 @@
+#[cfg(feature = "dim3")]
+use crate::geometry::shape::normalized_convex_polyhedron_mesh;
+use crate::geometry::shape::SharedShapeUtility;
+use crate::geometry::{
+ RawColliderSet, RawColliderShapeCastHit, RawPointProjection, RawRayIntersection, RawShape,
+ RawShapeCastHit, RawShapeContact, RawShapeType,
+};
+use crate::math::{RawRotation, RawVector};
+use crate::utils::{self, FlatHandle};
+use rapier::dynamics::MassProperties;
+use rapier::geometry::{ActiveCollisionTypes, ShapeType};
+use rapier::math::{IVector, Pose, Real, Rotation, Vector};
+use rapier::parry::query;
+use rapier::parry::query::ShapeCastOptions;
+use rapier::pipeline::{ActiveEvents, ActiveHooks};
+use wasm_bindgen::prelude::*;
+
+#[wasm_bindgen]
+impl RawColliderSet {
+ /// The world-space translation of this collider.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim2")]
+ pub fn coTranslation(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) {
+ self.map(handle, |co| {
+ let u = co.position().translation;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ });
+ }
+ /// The world-space translation of this collider.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim3")]
+ pub fn coTranslation(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) {
+ self.map(handle, |co| {
+ let u = co.position().translation;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ });
+ }
+
+ /// The world-space orientation of this collider.
+ #[cfg(feature = "dim2")]
+ pub fn coRotation(&self, handle: FlatHandle) -> f32 {
+ self.map(handle, |co| co.position().rotation.angle())
+ }
+
+ /// The world-space orientation of this collider.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim3")]
+ pub fn coRotation(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) {
+ self.map(handle, |co| {
+ let u = co.position().rotation;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ scratch_buffer.set_index(3, u.w);
+ });
+ }
+
+ /// The translation of this collider relative to its parent rigid-body.
+ ///
+ /// Returns `false` if it doesn’t have a parent.
+ #[cfg(feature = "dim2")]
+ pub fn coTranslationWrtParent(
+ &self,
+ handle: FlatHandle,
+ scratch_buffer: &js_sys::Float32Array,
+ ) -> bool {
+ self.map(handle, |co| {
+ co.position_wrt_parent().map_or(false, |pose| {
+ let u = pose.translation;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ true
+ })
+ })
+ }
+
+ /// The translation of this collider relative to its parent rigid-body.
+ ///
+ /// Returns `false` if it doesn’t have a parent.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim3")]
+ pub fn coTranslationWrtParent(
+ &self,
+ handle: FlatHandle,
+ scratch_buffer: &js_sys::Float32Array,
+ ) -> bool {
+ self.map(handle, |co| {
+ co.position_wrt_parent().map_or(false, |pose| {
+ let u = pose.translation;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ true
+ })
+ })
+ }
+
+ /// The orientation of this collider relative to its parent rigid-body.
+ ///
+ /// Returns `NAN` if it doesn’t have a parent.
+ #[cfg(feature = "dim2")]
+ pub fn coRotationWrtParent(&self, handle: FlatHandle) -> f32 {
+ self.map(handle, |co| {
+ co.position_wrt_parent()
+ .map_or(f32::NAN, |pose| pose.rotation.angle())
+ })
+ }
+
+ /// The orientation of this collider relative to its parent rigid-body.
+ ///
+ /// Returns `false` if it doesn’t have a parent.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim3")]
+ pub fn coRotationWrtParent(
+ &self,
+ handle: FlatHandle,
+ scratch_buffer: &js_sys::Float32Array,
+ ) -> bool {
+ self.map(handle, |co| {
+ co.position_wrt_parent().map_or(false, |pose| {
+ let u = pose.rotation;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ scratch_buffer.set_index(3, u.w);
+ true
+ })
+ })
+ }
+
+ /// Sets the translation of this collider.
+ ///
+ /// # Parameters
+ /// - `x`: the world-space position of the collider along the `x` axis.
+ /// - `y`: the world-space position of the collider along the `y` axis.
+ /// - `z`: the world-space position of the collider along the `z` axis.
+ /// - `wakeUp`: forces the collider to wake-up so it is properly affected by forces if it
+ /// wasn't moving before modifying its position.
+ #[cfg(feature = "dim3")]
+ pub fn coSetTranslation(&mut self, handle: FlatHandle, x: f32, y: f32, z: f32) {
+ self.map_mut(handle, |co| {
+ co.set_translation(Vector::new(x, y, z));
+ })
+ }
+
+ /// Sets the translation of this collider.
+ ///
+ /// # Parameters
+ /// - `x`: the world-space position of the collider along the `x` axis.
+ /// - `y`: the world-space position of the collider along the `y` axis.
+ /// - `wakeUp`: forces the collider to wake-up so it is properly affected by forces if it
+ /// wasn't moving before modifying its position.
+ #[cfg(feature = "dim2")]
+ pub fn coSetTranslation(&mut self, handle: FlatHandle, x: f32, y: f32) {
+ self.map_mut(handle, |co| {
+ co.set_translation(Vector::new(x, y));
+ })
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn coSetTranslationWrtParent(&mut self, handle: FlatHandle, x: f32, y: f32, z: f32) {
+ self.map_mut(handle, |co| {
+ co.set_translation_wrt_parent(Vector::new(x, y, z));
+ })
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn coSetTranslationWrtParent(&mut self, handle: FlatHandle, x: f32, y: f32) {
+ self.map_mut(handle, |co| {
+ co.set_translation_wrt_parent(Vector::new(x, y));
+ })
+ }
+
+ /// Sets the rotation quaternion of this collider.
+ ///
+ /// This does nothing if a zero quaternion is provided.
+ ///
+ /// # Parameters
+ /// - `x`: the first vector component of the quaternion.
+ /// - `y`: the second vector component of the quaternion.
+ /// - `z`: the third vector component of the quaternion.
+ /// - `w`: the scalar component of the quaternion.
+ /// - `wakeUp`: forces the collider to wake-up so it is properly affected by forces if it
+ /// wasn't moving before modifying its position.
+ #[cfg(feature = "dim3")]
+ pub fn coSetRotation(&mut self, handle: FlatHandle, x: f32, y: f32, z: f32, w: f32) {
+ let q = Rotation::from_xyzw(x, y, z, w);
+ if q.length_squared() != 0.0 {
+ let q = q.normalize();
+ self.map_mut(handle, |co| co.set_rotation(q))
+ }
+ }
+
+ /// Sets the rotation angle of this collider.
+ ///
+ /// # Parameters
+ /// - `angle`: the rotation angle, in radians.
+ /// - `wakeUp`: forces the collider to wake-up so it is properly affected by forces if it
+ /// wasn't moving before modifying its position.
+ #[cfg(feature = "dim2")]
+ pub fn coSetRotation(&mut self, handle: FlatHandle, angle: f32) {
+ self.map_mut(handle, |co| co.set_rotation(Rotation::new(angle)))
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn coSetRotationWrtParent(&mut self, handle: FlatHandle, x: f32, y: f32, z: f32, w: f32) {
+ let q = Rotation::from_xyzw(x, y, z, w);
+ if q.length_squared() != 0.0 {
+ let q = q.normalize();
+ self.map_mut(handle, |co| co.set_rotation_wrt_parent(q.to_scaled_axis()))
+ }
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn coSetRotationWrtParent(&mut self, handle: FlatHandle, angle: f32) {
+ self.map_mut(handle, |co| co.set_rotation_wrt_parent(angle))
+ }
+
+ /// Is this collider a sensor?
+ pub fn coIsSensor(&self, handle: FlatHandle) -> bool {
+ self.map(handle, |co| co.is_sensor())
+ }
+
+ /// The type of the shape of this collider.
+ pub fn coShapeType(&self, handle: FlatHandle) -> RawShapeType {
+ self.map(handle, |co| match co.shape().shape_type() {
+ ShapeType::Ball => RawShapeType::Ball,
+ ShapeType::Cuboid => RawShapeType::Cuboid,
+ ShapeType::Capsule => RawShapeType::Capsule,
+ ShapeType::Segment => RawShapeType::Segment,
+ ShapeType::Polyline => RawShapeType::Polyline,
+ ShapeType::Triangle => RawShapeType::Triangle,
+ ShapeType::TriMesh => RawShapeType::TriMesh,
+ ShapeType::HeightField => RawShapeType::HeightField,
+ ShapeType::Compound => RawShapeType::Compound,
+ ShapeType::HalfSpace => RawShapeType::HalfSpace,
+ ShapeType::Voxels => RawShapeType::Voxels,
+ #[cfg(feature = "dim3")]
+ ShapeType::ConvexPolyhedron => RawShapeType::ConvexPolyhedron,
+ #[cfg(feature = "dim2")]
+ ShapeType::ConvexPolygon => RawShapeType::ConvexPolygon,
+ #[cfg(feature = "dim3")]
+ ShapeType::Cylinder => RawShapeType::Cylinder,
+ #[cfg(feature = "dim3")]
+ ShapeType::Cone => RawShapeType::Cone,
+ ShapeType::RoundCuboid => RawShapeType::RoundCuboid,
+ ShapeType::RoundTriangle => RawShapeType::RoundTriangle,
+ #[cfg(feature = "dim3")]
+ ShapeType::RoundCylinder => RawShapeType::RoundCylinder,
+ #[cfg(feature = "dim3")]
+ ShapeType::RoundCone => RawShapeType::RoundCone,
+ #[cfg(feature = "dim3")]
+ ShapeType::RoundConvexPolyhedron => RawShapeType::RoundConvexPolyhedron,
+ #[cfg(feature = "dim2")]
+ ShapeType::RoundConvexPolygon => RawShapeType::RoundConvexPolygon,
+ ShapeType::Custom => panic!("Not yet implemented."),
+ })
+ }
+
+ pub fn coShape(&self, handle: FlatHandle) -> RawShape {
+ self.map(handle, |co| RawShape(co.shared_shape().clone()))
+ }
+
+ /// The outward normal of this collider if it has a half-space shape.
+ ///
+ /// Returns `false` if it doesn’t have a half-space shape.
+ #[cfg(feature = "dim2")]
+ pub fn coHalfspaceNormal(
+ &self,
+ handle: FlatHandle,
+ scratch_buffer: &js_sys::Float32Array,
+ ) -> bool {
+ self.map(handle, |co| {
+ co.shape().as_halfspace().map_or(false, |h| {
+ let u = h.normal;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ true
+ })
+ })
+ }
+
+ /// The outward normal of this collider if it has a half-space shape.
+ ///
+ /// Returns `false` if it doesn’t have a half-space shape.
+ #[cfg(feature = "dim3")]
+ pub fn coHalfspaceNormal(
+ &self,
+ handle: FlatHandle,
+ scratch_buffer: &js_sys::Float32Array,
+ ) -> bool {
+ self.map(handle, |co| {
+ co.shape().as_halfspace().map_or(false, |h| {
+ let u = h.normal;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ true
+ })
+ })
+ }
+
+ /// The half-extents of this collider if it has a cuboid shape.
+ ///
+ /// Returns `false` if it doesn’t have a cuboid shape.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim2")]
+ pub fn coHalfExtents(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) -> bool {
+ self.map(handle, |co| {
+ co.shape().as_cuboid().map_or_else(
+ || {
+ co.shape().as_round_cuboid().map_or(false, |c| {
+ let u = c.inner_shape.half_extents;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ true
+ })
+ },
+ |c| {
+ let u = c.half_extents;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ true
+ },
+ )
+ })
+ }
+
+ /// The half-extents of this collider if it has a cuboid shape.
+ ///
+ /// Returns `false` if it doesn’t have a cuboid shape.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim3")]
+ pub fn coHalfExtents(&self, handle: FlatHandle, scratch_buffer: &js_sys::Float32Array) -> bool {
+ self.map(handle, |co| {
+ co.shape().as_cuboid().map_or_else(
+ || {
+ co.shape().as_round_cuboid().map_or(false, |c| {
+ let u = c.inner_shape.half_extents;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ true
+ })
+ },
+ |c| {
+ let u = c.half_extents;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ true
+ },
+ )
+ })
+ }
+
+ /// Set the half-extents of this collider if it has a cuboid shape.
+ pub fn coSetHalfExtents(&mut self, handle: FlatHandle, newHalfExtents: &RawVector) {
+ self.map_mut(handle, |co| match co.shape().shape_type() {
+ ShapeType::Cuboid => co
+ .shape_mut()
+ .as_cuboid_mut()
+ .map(|b| b.half_extents = newHalfExtents.0.into()),
+ ShapeType::RoundCuboid => co
+ .shape_mut()
+ .as_round_cuboid_mut()
+ .map(|b| b.inner_shape.half_extents = newHalfExtents.0.into()),
+ _ => None,
+ });
+ }
+
+ /// The radius of this collider if it is a ball, capsule, cylinder, or cone shape.
+ pub fn coRadius(&self, handle: FlatHandle) -> Option {
+ self.map(handle, |co| match co.shape().shape_type() {
+ ShapeType::Ball => co.shape().as_ball().map(|b| b.radius),
+ ShapeType::Capsule => co.shape().as_capsule().map(|b| b.radius),
+ #[cfg(feature = "dim3")]
+ ShapeType::Cylinder => co.shape().as_cylinder().map(|b| b.radius),
+ #[cfg(feature = "dim3")]
+ ShapeType::RoundCylinder => {
+ co.shape().as_round_cylinder().map(|b| b.inner_shape.radius)
+ }
+ #[cfg(feature = "dim3")]
+ ShapeType::Cone => co.shape().as_cone().map(|b| b.radius),
+ #[cfg(feature = "dim3")]
+ ShapeType::RoundCone => co.shape().as_round_cone().map(|b| b.inner_shape.radius),
+ _ => None,
+ })
+ }
+
+ /// Set the radius of this collider if it is a ball, capsule, cylinder, or cone shape.
+ pub fn coSetRadius(&mut self, handle: FlatHandle, newRadius: Real) {
+ self.map_mut(handle, |co| match co.shape().shape_type() {
+ ShapeType::Ball => co.shape_mut().as_ball_mut().map(|b| b.radius = newRadius),
+ ShapeType::Capsule => co
+ .shape_mut()
+ .as_capsule_mut()
+ .map(|b| b.radius = newRadius),
+ #[cfg(feature = "dim3")]
+ ShapeType::Cylinder => co
+ .shape_mut()
+ .as_cylinder_mut()
+ .map(|b| b.radius = newRadius),
+ #[cfg(feature = "dim3")]
+ ShapeType::RoundCylinder => co
+ .shape_mut()
+ .as_round_cylinder_mut()
+ .map(|b| b.inner_shape.radius = newRadius),
+ #[cfg(feature = "dim3")]
+ ShapeType::Cone => co.shape_mut().as_cone_mut().map(|b| b.radius = newRadius),
+ #[cfg(feature = "dim3")]
+ ShapeType::RoundCone => co
+ .shape_mut()
+ .as_round_cone_mut()
+ .map(|b| b.inner_shape.radius = newRadius),
+ _ => None,
+ });
+ }
+
+ /// The half height of this collider if it is a capsule, cylinder, or cone shape.
+ pub fn coHalfHeight(&self, handle: FlatHandle) -> Option {
+ self.map(handle, |co| match co.shape().shape_type() {
+ ShapeType::Capsule => co.shape().as_capsule().map(|b| b.half_height()),
+ #[cfg(feature = "dim3")]
+ ShapeType::Cylinder => co.shape().as_cylinder().map(|b| b.half_height),
+ #[cfg(feature = "dim3")]
+ ShapeType::RoundCylinder => co
+ .shape()
+ .as_round_cylinder()
+ .map(|b| b.inner_shape.half_height),
+ #[cfg(feature = "dim3")]
+ ShapeType::Cone => co.shape().as_cone().map(|b| b.half_height),
+ #[cfg(feature = "dim3")]
+ ShapeType::RoundCone => co
+ .shape()
+ .as_round_cone()
+ .map(|b| b.inner_shape.half_height),
+ _ => None,
+ })
+ }
+
+ /// Set the half height of this collider if it is a capsule, cylinder, or cone shape.
+ pub fn coSetHalfHeight(&mut self, handle: FlatHandle, newHalfheight: Real) {
+ self.map_mut(handle, |co| match co.shape().shape_type() {
+ ShapeType::Capsule => {
+ let point = Vector::Y * newHalfheight;
+ co.shape_mut().as_capsule_mut().map(|b| {
+ b.segment.a = -point;
+ b.segment.b = point;
+ })
+ }
+ #[cfg(feature = "dim3")]
+ ShapeType::Cylinder => co
+ .shape_mut()
+ .as_cylinder_mut()
+ .map(|b| b.half_height = newHalfheight),
+ #[cfg(feature = "dim3")]
+ ShapeType::RoundCylinder => co
+ .shape_mut()
+ .as_round_cylinder_mut()
+ .map(|b| b.inner_shape.half_height = newHalfheight),
+ #[cfg(feature = "dim3")]
+ ShapeType::Cone => co
+ .shape_mut()
+ .as_cone_mut()
+ .map(|b| b.half_height = newHalfheight),
+ #[cfg(feature = "dim3")]
+ ShapeType::RoundCone => co
+ .shape_mut()
+ .as_round_cone_mut()
+ .map(|b| b.inner_shape.half_height = newHalfheight),
+ _ => None,
+ });
+ }
+
+ /// The radius of the round edges of this collider.
+ pub fn coRoundRadius(&self, handle: FlatHandle) -> Option {
+ self.map(handle, |co| match co.shape().shape_type() {
+ ShapeType::RoundCuboid => co.shape().as_round_cuboid().map(|b| b.border_radius),
+ ShapeType::RoundTriangle => co.shape().as_round_triangle().map(|b| b.border_radius),
+ #[cfg(feature = "dim3")]
+ ShapeType::RoundCylinder => co.shape().as_round_cylinder().map(|b| b.border_radius),
+ #[cfg(feature = "dim3")]
+ ShapeType::RoundCone => co.shape().as_round_cone().map(|b| b.border_radius),
+ #[cfg(feature = "dim3")]
+ ShapeType::RoundConvexPolyhedron => co
+ .shape()
+ .as_round_convex_polyhedron()
+ .map(|b| b.border_radius),
+ #[cfg(feature = "dim2")]
+ ShapeType::RoundConvexPolygon => co
+ .shape()
+ .as_round_convex_polygon()
+ .map(|b| b.border_radius),
+ _ => None,
+ })
+ }
+
+ /// Set the radius of the round edges of this collider.
+ pub fn coSetRoundRadius(&mut self, handle: FlatHandle, newBorderRadius: Real) {
+ self.map_mut(handle, |co| match co.shape().shape_type() {
+ ShapeType::RoundCuboid => co
+ .shape_mut()
+ .as_round_cuboid_mut()
+ .map(|b| b.border_radius = newBorderRadius),
+ ShapeType::RoundTriangle => co
+ .shape_mut()
+ .as_round_triangle_mut()
+ .map(|b| b.border_radius = newBorderRadius),
+ #[cfg(feature = "dim3")]
+ ShapeType::RoundCylinder => co
+ .shape_mut()
+ .as_round_cylinder_mut()
+ .map(|b| b.border_radius = newBorderRadius),
+ #[cfg(feature = "dim3")]
+ ShapeType::RoundCone => co
+ .shape_mut()
+ .as_round_cone_mut()
+ .map(|b| b.border_radius = newBorderRadius),
+ #[cfg(feature = "dim3")]
+ ShapeType::RoundConvexPolyhedron => co
+ .shape_mut()
+ .as_round_convex_polyhedron_mut()
+ .map(|b| b.border_radius = newBorderRadius),
+ #[cfg(feature = "dim2")]
+ ShapeType::RoundConvexPolygon => co
+ .shape_mut()
+ .as_round_convex_polygon_mut()
+ .map(|b| b.border_radius = newBorderRadius),
+ _ => None,
+ });
+ }
+
+ pub fn coVoxelData(&self, handle: FlatHandle) -> Option> {
+ self.map(handle, |co| {
+ let vox = co.shape().as_voxels()?;
+ let coords = vox
+ .voxels()
+ .filter_map(|vox| (!vox.state.is_empty()).then_some(vox.grid_coords))
+ .flat_map(|ids| ids.to_array())
+ .collect();
+ Some(coords)
+ })
+ }
+
+ pub fn coVoxelSize(&self, handle: FlatHandle) -> Option {
+ self.map(handle, |co| {
+ let vox = co.shape().as_voxels()?;
+ Some(RawVector(vox.voxel_size()))
+ })
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn coSetVoxel(&mut self, handle: FlatHandle, ix: i32, iy: i32, filled: bool) {
+ self.map_mut(handle, |co| {
+ if let Some(vox) = co.shape_mut().as_voxels_mut() {
+ vox.set_voxel(IVector::new(ix, iy), filled);
+ }
+ })
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn coSetVoxel(&mut self, handle: FlatHandle, ix: i32, iy: i32, iz: i32, filled: bool) {
+ self.map_mut(handle, |co| {
+ if let Some(vox) = co.shape_mut().as_voxels_mut() {
+ vox.set_voxel(IVector::new(ix, iy, iz), filled);
+ }
+ })
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn coPropagateVoxelChange(
+ &mut self,
+ handle1: FlatHandle,
+ handle2: FlatHandle,
+ ix: i32,
+ iy: i32,
+ shift_x: i32,
+ shift_y: i32,
+ ) {
+ self.map_pair_mut(handle1, handle2, |co1, co2| {
+ if let (Some(co1), Some(co2)) = (co1, co2) {
+ if let (Some(vox1), Some(vox2)) = (
+ co1.shape_mut().as_voxels_mut(),
+ co2.shape_mut().as_voxels_mut(),
+ ) {
+ vox1.propagate_voxel_change(
+ vox2,
+ IVector::new(ix, iy),
+ IVector::new(shift_x, shift_y),
+ );
+ }
+ }
+ })
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn coPropagateVoxelChange(
+ &mut self,
+ handle1: FlatHandle,
+ handle2: FlatHandle,
+ ix: i32,
+ iy: i32,
+ iz: i32,
+ shift_x: i32,
+ shift_y: i32,
+ shift_z: i32,
+ ) {
+ self.map_pair_mut(handle1, handle2, |co1, co2| {
+ if let (Some(co1), Some(co2)) = (co1, co2) {
+ if let (Some(vox1), Some(vox2)) = (
+ co1.shape_mut().as_voxels_mut(),
+ co2.shape_mut().as_voxels_mut(),
+ ) {
+ vox1.propagate_voxel_change(
+ vox2,
+ IVector::new(ix, iy, iz),
+ IVector::new(shift_x, shift_y, shift_z),
+ );
+ }
+ }
+ })
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn coCombineVoxelStates(
+ &mut self,
+ handle1: FlatHandle,
+ handle2: FlatHandle,
+ shift_x: i32,
+ shift_y: i32,
+ ) {
+ self.map_pair_mut(handle1, handle2, |co1, co2| {
+ if let (Some(co1), Some(co2)) = (co1, co2) {
+ if let (Some(vox1), Some(vox2)) = (
+ co1.shape_mut().as_voxels_mut(),
+ co2.shape_mut().as_voxels_mut(),
+ ) {
+ vox1.combine_voxel_states(vox2, IVector::new(shift_x, shift_y));
+ }
+ }
+ })
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn coCombineVoxelStates(
+ &mut self,
+ handle1: FlatHandle,
+ handle2: FlatHandle,
+ shift_x: i32,
+ shift_y: i32,
+ shift_z: i32,
+ ) {
+ self.map_pair_mut(handle1, handle2, |co1, co2| {
+ if let (Some(co1), Some(co2)) = (co1, co2) {
+ if let (Some(vox1), Some(vox2)) = (
+ co1.shape_mut().as_voxels_mut(),
+ co2.shape_mut().as_voxels_mut(),
+ ) {
+ vox1.combine_voxel_states(vox2, IVector::new(shift_x, shift_y, shift_z));
+ }
+ }
+ })
+ }
+
+ /// The vertices of this triangle mesh, polyline, convex polyhedron, segment, triangle or convex polyhedron, if it is one.
+ ///
+ /// For convex polyhedra, this returns the vertices of a convex hull recomputed with
+ /// `try_convex_hull`, so they may differ in count and order from the points the shape
+ /// was built from. This guarantees the result can be used to reconstruct the shape.
+ pub fn coVertices(&self, handle: FlatHandle) -> Option> {
+ let flatten =
+ |vertices: &[Vector]| vertices.iter().flat_map(|p| p.to_array()).collect();
+ self.map(handle, |co| match co.shape().shape_type() {
+ ShapeType::TriMesh => co.shape().as_trimesh().map(|t| flatten(t.vertices())),
+ #[cfg(feature = "dim2")]
+ ShapeType::Polyline => co.shape().as_polyline().map(|p| flatten(p.vertices())),
+ #[cfg(feature = "dim3")]
+ ShapeType::ConvexPolyhedron => co
+ .shape()
+ .as_convex_polyhedron()
+ .and_then(normalized_convex_polyhedron_mesh)
+ .map(|(points, _)| flatten(&points)),
+ #[cfg(feature = "dim3")]
+ ShapeType::RoundConvexPolyhedron => co
+ .shape()
+ .as_round_convex_polyhedron()
+ .and_then(|p| normalized_convex_polyhedron_mesh(&p.inner_shape))
+ .map(|(points, _)| flatten(&points)),
+ #[cfg(feature = "dim2")]
+ ShapeType::ConvexPolygon => co.shape().as_convex_polygon().map(|p| flatten(p.points())),
+ #[cfg(feature = "dim2")]
+ ShapeType::RoundConvexPolygon => co
+ .shape()
+ .as_round_convex_polygon()
+ .map(|p| flatten(p.inner_shape.points())),
+ ShapeType::Segment => co.shape().as_segment().map(|s| flatten(&[s.a, s.b])),
+ ShapeType::RoundTriangle => co
+ .shape()
+ .as_round_triangle()
+ .map(|t| flatten(&[t.inner_shape.a, t.inner_shape.b, t.inner_shape.c])),
+ ShapeType::Triangle => co.shape().as_triangle().map(|t| flatten(&[t.a, t.b, t.c])),
+ _ => None,
+ })
+ }
+
+ /// The indices of this triangle mesh, polyline, or convex polyhedron, if it is one.
+ ///
+ /// For convex polyhedra, the indices refer to the convex hull recomputed with
+ /// `try_convex_hull` (matching `coVertices`), not to the original input mesh.
+ pub fn coIndices(&self, handle: FlatHandle) -> Option> {
+ self.map(handle, |co| match co.shape().shape_type() {
+ ShapeType::TriMesh => co
+ .shape()
+ .as_trimesh()
+ .map(|t| t.indices().iter().flat_map(|p| p.iter()).copied().collect()),
+ ShapeType::Polyline => co
+ .shape()
+ .as_polyline()
+ .map(|p| p.indices().iter().flat_map(|p| p.iter()).copied().collect()),
+ #[cfg(feature = "dim3")]
+ ShapeType::ConvexPolyhedron => co
+ .shape()
+ .as_convex_polyhedron()
+ .and_then(normalized_convex_polyhedron_mesh)
+ .map(|(_, indices)| indices),
+ #[cfg(feature = "dim3")]
+ ShapeType::RoundConvexPolyhedron => co
+ .shape()
+ .as_round_convex_polyhedron()
+ .and_then(|p| normalized_convex_polyhedron_mesh(&p.inner_shape))
+ .map(|(_, indices)| indices),
+ _ => None,
+ })
+ }
+
+ pub fn coTriMeshFlags(&self, handle: FlatHandle) -> Option {
+ self.map(handle, |co| {
+ co.shape().as_trimesh().map(|tri| tri.flags().bits() as u32)
+ })
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn coHeightFieldFlags(&self, handle: FlatHandle) -> Option {
+ self.map(handle, |co| {
+ co.shape()
+ .as_heightfield()
+ .map(|hf| hf.flags().bits() as u32)
+ })
+ }
+
+ /// The height of this heightfield if it is one.
+ pub fn coHeightfieldHeights(&self, handle: FlatHandle) -> Option> {
+ self.map(handle, |co| match co.shape().shape_type() {
+ ShapeType::HeightField => co.shape().as_heightfield().map(|h| {
+ #[cfg(feature = "dim2")]
+ {
+ h.heights().as_slice().to_vec()
+ }
+ #[cfg(feature = "dim3")]
+ {
+ h.heights().data().to_vec()
+ }
+ }),
+ _ => None,
+ })
+ }
+
+ /// The scaling factor applied to this heightfield if it is one.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim2")]
+ pub fn coHeightfieldScale(
+ &self,
+ handle: FlatHandle,
+ scratch_buffer: &js_sys::Float32Array,
+ ) -> bool {
+ self.map(handle, |co| match co.shape().shape_type() {
+ ShapeType::HeightField => co.shape().as_heightfield().map_or(false, |h| {
+ let u = h.scale();
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ true
+ }),
+ _ => false,
+ })
+ }
+
+ /// The scaling factor applied to this heightfield if it is one.
+ ///
+ /// # Parameters
+ /// - `scratch_buffer`: The array to be populated.
+ #[cfg(feature = "dim3")]
+ pub fn coHeightfieldScale(
+ &self,
+ handle: FlatHandle,
+ scratch_buffer: &js_sys::Float32Array,
+ ) -> bool {
+ self.map(handle, |co| match co.shape().shape_type() {
+ ShapeType::HeightField => co.shape().as_heightfield().map_or(false, |h| {
+ let u = h.scale();
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ true
+ }),
+ _ => false,
+ })
+ }
+
+ /// The number of rows on this heightfield's height matrix, if it is one.
+ #[cfg(feature = "dim3")]
+ pub fn coHeightfieldNRows(&self, handle: FlatHandle) -> Option {
+ self.map(handle, |co| match co.shape().shape_type() {
+ ShapeType::HeightField => co.shape().as_heightfield().map(|h| h.nrows()),
+ _ => None,
+ })
+ }
+
+ /// The number of columns on this heightfield's height matrix, if it is one.
+ #[cfg(feature = "dim3")]
+ pub fn coHeightfieldNCols(&self, handle: FlatHandle) -> Option {
+ self.map(handle, |co| match co.shape().shape_type() {
+ ShapeType::HeightField => co.shape().as_heightfield().map(|h| h.ncols()),
+ _ => None,
+ })
+ }
+
+ /// The unique integer identifier of the collider this collider is attached to.
+ pub fn coParent(&self, handle: FlatHandle) -> Option {
+ self.map(handle, |co| co.parent().map(|p| utils::flat_handle(p.0)))
+ }
+
+ pub fn coSetEnabled(&mut self, handle: FlatHandle, enabled: bool) {
+ self.map_mut(handle, |co| co.set_enabled(enabled))
+ }
+
+ pub fn coIsEnabled(&self, handle: FlatHandle) -> bool {
+ self.map(handle, |co| co.is_enabled())
+ }
+
+ pub fn coSetContactSkin(&mut self, handle: FlatHandle, contact_skin: f32) {
+ self.map_mut(handle, |co| co.set_contact_skin(contact_skin))
+ }
+
+ pub fn coContactSkin(&self, handle: FlatHandle) -> f32 {
+ self.map(handle, |co| co.contact_skin())
+ }
+
+ /// The friction coefficient of this collider.
+ pub fn coFriction(&self, handle: FlatHandle) -> f32 {
+ self.map(handle, |co| co.material().friction)
+ }
+ /// The restitution coefficient of this collider.
+ pub fn coRestitution(&self, handle: FlatHandle) -> f32 {
+ self.map(handle, |co| co.material().restitution)
+ }
+
+ /// The density of this collider.
+ pub fn coDensity(&self, handle: FlatHandle) -> f32 {
+ self.map(handle, |co| co.density())
+ }
+
+ /// The mass of this collider.
+ pub fn coMass(&self, handle: FlatHandle) -> f32 {
+ self.map(handle, |co| co.mass())
+ }
+
+ /// The volume of this collider.
+ pub fn coVolume(&self, handle: FlatHandle) -> f32 {
+ self.map(handle, |co| co.volume())
+ }
+
+ /// The collision groups of this collider.
+ pub fn coCollisionGroups(&self, handle: FlatHandle) -> u32 {
+ self.map(handle, |co| {
+ super::pack_interaction_groups(co.collision_groups())
+ })
+ }
+
+ /// The solver groups of this collider.
+ pub fn coSolverGroups(&self, handle: FlatHandle) -> u32 {
+ self.map(handle, |co| {
+ super::pack_interaction_groups(co.solver_groups())
+ })
+ }
+
+ /// The physics hooks enabled for this collider.
+ pub fn coActiveHooks(&self, handle: FlatHandle) -> u32 {
+ self.map(handle, |co| co.active_hooks().bits())
+ }
+
+ /// The collision types enabled for this collider.
+ pub fn coActiveCollisionTypes(&self, handle: FlatHandle) -> u16 {
+ self.map(handle, |co| co.active_collision_types().bits())
+ }
+
+ /// The events enabled for this collider.
+ pub fn coActiveEvents(&self, handle: FlatHandle) -> u32 {
+ self.map(handle, |co| co.active_events().bits())
+ }
+
+ /// The total force magnitude beyond which a contact force event can be emitted.
+ pub fn coContactForceEventThreshold(&self, handle: FlatHandle) -> f32 {
+ self.map(handle, |co| co.contact_force_event_threshold())
+ }
+
+ pub fn coContainsPoint(&self, handle: FlatHandle, point: &RawVector) -> bool {
+ self.map(handle, |co| {
+ co.shared_shape()
+ .containsPoint(co.position(), &point.0.into())
+ })
+ }
+
+ pub fn coCastShape(
+ &self,
+ handle: FlatHandle,
+ colliderVel: &RawVector,
+ shape2: &RawShape,
+ shape2Pos: &RawVector,
+ shape2Rot: &RawRotation,
+ shape2Vel: &RawVector,
+ target_distance: f32,
+ maxToi: f32,
+ stop_at_penetration: bool,
+ ) -> Option {
+ let pos2 = Pose::from_parts(shape2Pos.0.into(), shape2Rot.0);
+
+ self.map(handle, |co| {
+ let pos1 = co.position();
+ co.shared_shape().castShape(
+ pos1,
+ &colliderVel.0.into(),
+ &*shape2.0,
+ &pos2,
+ &shape2Vel.0.into(),
+ target_distance,
+ maxToi,
+ stop_at_penetration,
+ )
+ })
+ }
+
+ pub fn coCastCollider(
+ &self,
+ handle: FlatHandle,
+ collider1Vel: &RawVector,
+ collider2handle: FlatHandle,
+ collider2Vel: &RawVector,
+ target_distance: f32,
+ max_toi: f32,
+ stop_at_penetration: bool,
+ ) -> Option {
+ let handle2 = utils::collider_handle(collider2handle);
+ let co2 = self
+ .0
+ .get(handle2)
+ .expect("Invalid Collider reference. It may have been removed from the physics World.");
+
+ self.map(handle, |co| {
+ query::cast_shapes(
+ co.position(),
+ collider1Vel.0,
+ co.shape(),
+ co2.position(),
+ collider2Vel.0,
+ co2.shape(),
+ ShapeCastOptions {
+ max_time_of_impact: max_toi,
+ stop_at_penetration,
+ target_distance,
+ compute_impact_geometry_on_penetration: true,
+ },
+ )
+ .unwrap_or(None)
+ .map_or(None, |hit| {
+ Some(RawColliderShapeCastHit {
+ handle: handle2,
+ hit,
+ })
+ })
+ })
+ }
+
+ pub fn coIntersectsShape(
+ &self,
+ handle: FlatHandle,
+ shape2: &RawShape,
+ shapePos2: &RawVector,
+ shapeRot2: &RawRotation,
+ ) -> bool {
+ let pos2 = Pose::from_parts(shapePos2.0.into(), shapeRot2.0);
+
+ self.map(handle, |co| {
+ co.shared_shape()
+ .intersectsShape(co.position(), &*shape2.0, &pos2)
+ })
+ }
+
+ pub fn coContactShape(
+ &self,
+ handle: FlatHandle,
+ shape2: &RawShape,
+ shapePos2: &RawVector,
+ shapeRot2: &RawRotation,
+ prediction: f32,
+ ) -> Option {
+ let pos2 = Pose::from_parts(shapePos2.0.into(), shapeRot2.0);
+
+ self.map(handle, |co| {
+ co.shared_shape()
+ .contactShape(co.position(), &*shape2.0, &pos2, prediction)
+ })
+ }
+
+ pub fn coContactCollider(
+ &self,
+ handle: FlatHandle,
+ collider2handle: FlatHandle,
+ prediction: f32,
+ ) -> Option {
+ let co2 = self
+ .0
+ .get(utils::collider_handle(collider2handle))
+ .expect("Invalid Collider reference. It may have been removed from the physics World.");
+
+ self.map(handle, |co| {
+ query::contact(
+ co.position(),
+ co.shape(),
+ &co2.position(),
+ co2.shape(),
+ prediction,
+ )
+ .ok()
+ .flatten()
+ .map(|contact| RawShapeContact { contact })
+ })
+ }
+
+ pub fn coProjectPoint(
+ &self,
+ handle: FlatHandle,
+ point: &RawVector,
+ solid: bool,
+ ) -> RawPointProjection {
+ self.map(handle, |co| {
+ co.shared_shape()
+ .projectPoint(co.position(), &point.0.into(), solid)
+ })
+ }
+
+ pub fn coIntersectsRay(
+ &self,
+ handle: FlatHandle,
+ rayOrig: &RawVector,
+ rayDir: &RawVector,
+ maxToi: f32,
+ ) -> bool {
+ self.map(handle, |co| {
+ co.shared_shape().intersectsRay(
+ co.position(),
+ rayOrig.0.into(),
+ rayDir.0.into(),
+ maxToi,
+ )
+ })
+ }
+
+ pub fn coCastRay(
+ &self,
+ handle: FlatHandle,
+ rayOrig: &RawVector,
+ rayDir: &RawVector,
+ maxToi: f32,
+ solid: bool,
+ ) -> f32 {
+ self.map(handle, |co| {
+ co.shared_shape().castRay(
+ co.position(),
+ rayOrig.0.into(),
+ rayDir.0.into(),
+ maxToi,
+ solid,
+ )
+ })
+ }
+
+ pub fn coCastRayAndGetNormal(
+ &self,
+ handle: FlatHandle,
+ rayOrig: &RawVector,
+ rayDir: &RawVector,
+ maxToi: f32,
+ solid: bool,
+ ) -> Option {
+ self.map(handle, |co| {
+ co.shared_shape().castRayAndGetNormal(
+ co.position(),
+ rayOrig.0.into(),
+ rayDir.0.into(),
+ maxToi,
+ solid,
+ )
+ })
+ }
+
+ pub fn coSetSensor(&mut self, handle: FlatHandle, is_sensor: bool) {
+ self.map_mut(handle, |co| co.set_sensor(is_sensor))
+ }
+
+ pub fn coSetRestitution(&mut self, handle: FlatHandle, restitution: f32) {
+ self.map_mut(handle, |co| co.set_restitution(restitution))
+ }
+
+ pub fn coSetFriction(&mut self, handle: FlatHandle, friction: f32) {
+ self.map_mut(handle, |co| co.set_friction(friction))
+ }
+
+ pub fn coFrictionCombineRule(&self, handle: FlatHandle) -> u32 {
+ self.map(handle, |co| co.friction_combine_rule() as u32)
+ }
+
+ pub fn coSetFrictionCombineRule(&mut self, handle: FlatHandle, rule: u32) {
+ let rule = super::combine_rule_from_u32(rule);
+ self.map_mut(handle, |co| co.set_friction_combine_rule(rule))
+ }
+
+ pub fn coRestitutionCombineRule(&self, handle: FlatHandle) -> u32 {
+ self.map(handle, |co| co.restitution_combine_rule() as u32)
+ }
+
+ pub fn coSetRestitutionCombineRule(&mut self, handle: FlatHandle, rule: u32) {
+ let rule = super::combine_rule_from_u32(rule);
+ self.map_mut(handle, |co| co.set_restitution_combine_rule(rule))
+ }
+
+ pub fn coSetCollisionGroups(&mut self, handle: FlatHandle, groups: u32) {
+ let groups = super::unpack_interaction_groups(groups);
+ self.map_mut(handle, |co| co.set_collision_groups(groups))
+ }
+
+ pub fn coSetSolverGroups(&mut self, handle: FlatHandle, groups: u32) {
+ let groups = super::unpack_interaction_groups(groups);
+ self.map_mut(handle, |co| co.set_solver_groups(groups))
+ }
+
+ pub fn coSetActiveHooks(&mut self, handle: FlatHandle, hooks: u32) {
+ let hooks = ActiveHooks::from_bits(hooks).unwrap_or(ActiveHooks::empty());
+ self.map_mut(handle, |co| co.set_active_hooks(hooks));
+ }
+
+ pub fn coSetActiveEvents(&mut self, handle: FlatHandle, events: u32) {
+ let events = ActiveEvents::from_bits(events).unwrap_or(ActiveEvents::empty());
+ self.map_mut(handle, |co| co.set_active_events(events))
+ }
+
+ pub fn coSetActiveCollisionTypes(&mut self, handle: FlatHandle, types: u16) {
+ let types = ActiveCollisionTypes::from_bits(types).unwrap_or(ActiveCollisionTypes::empty());
+ self.map_mut(handle, |co| co.set_active_collision_types(types));
+ }
+
+ pub fn coSetShape(&mut self, handle: FlatHandle, shape: &RawShape) {
+ self.map_mut(handle, |co| co.set_shape(shape.0.clone()));
+ }
+
+ pub fn coSetContactForceEventThreshold(&mut self, handle: FlatHandle, threshold: f32) {
+ self.map_mut(handle, |co| co.set_contact_force_event_threshold(threshold))
+ }
+
+ pub fn coSetDensity(&mut self, handle: FlatHandle, density: f32) {
+ self.map_mut(handle, |co| co.set_density(density))
+ }
+
+ pub fn coSetMass(&mut self, handle: FlatHandle, mass: f32) {
+ self.map_mut(handle, |co| co.set_mass(mass))
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn coSetMassProperties(
+ &mut self,
+ handle: FlatHandle,
+ mass: f32,
+ centerOfMass: &RawVector,
+ principalAngularInertia: &RawVector,
+ angularInertiaFrame: &RawRotation,
+ ) {
+ self.map_mut(handle, |co| {
+ let mprops = MassProperties::with_principal_inertia_frame(
+ centerOfMass.0.into(),
+ mass,
+ principalAngularInertia.0,
+ angularInertiaFrame.0,
+ );
+
+ co.set_mass_properties(mprops)
+ })
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn coSetMassProperties(
+ &mut self,
+ handle: FlatHandle,
+ mass: f32,
+ centerOfMass: &RawVector,
+ principalAngularInertia: f32,
+ ) {
+ self.map_mut(handle, |co| {
+ let props = MassProperties::new(centerOfMass.0.into(), mass, principalAngularInertia);
+ co.set_mass_properties(props)
+ })
+ }
+}
diff --git a/typescript/src/geometry/collider_set.rs b/typescript/src/geometry/collider_set.rs
new file mode 100644
index 000000000..14e715263
--- /dev/null
+++ b/typescript/src/geometry/collider_set.rs
@@ -0,0 +1,293 @@
+use crate::dynamics::{RawIslandManager, RawRigidBodySet};
+use crate::geometry::RawShape;
+use crate::math::{RawRotation, RawVector};
+use crate::utils::{self, FlatHandle};
+use rapier::prelude::*;
+use wasm_bindgen::prelude::*;
+
+// NOTE: this MUST match the same enum on the TS side.
+enum MassPropsMode {
+ Density = 0,
+ Mass,
+ MassProps,
+}
+
+#[wasm_bindgen]
+pub struct RawColliderSet(pub(crate) ColliderSet);
+
+impl RawColliderSet {
+ pub(crate) fn map(&self, handle: FlatHandle, f: impl FnOnce(&Collider) -> T) -> T {
+ let collider = self
+ .0
+ .get(utils::collider_handle(handle))
+ .expect("Invalid Collider reference. It may have been removed from the physics World.");
+ f(collider)
+ }
+
+ pub(crate) fn map_mut(
+ &mut self,
+ handle: FlatHandle,
+ f: impl FnOnce(&mut Collider) -> T,
+ ) -> T {
+ let collider = self
+ .0
+ .get_mut(utils::collider_handle(handle))
+ .expect("Invalid Collider reference. It may have been removed from the physics World.");
+ f(collider)
+ }
+
+ pub(crate) fn map_pair_mut(
+ &mut self,
+ handle1: FlatHandle,
+ handle2: FlatHandle,
+ f: impl FnOnce(Option<&mut Collider>, Option<&mut Collider>) -> T,
+ ) -> T {
+ let (collider1, collider2) = self.0.get_pair_mut(
+ utils::collider_handle(handle1),
+ utils::collider_handle(handle2),
+ );
+ f(collider1, collider2)
+ }
+}
+
+impl RawColliderSet {
+ // This is a workaround because wasm-bindgen doesn't support the `cfg(feature = ...)`
+ // for the method arguments.
+ pub fn do_create_collider(
+ &mut self,
+ enabled: bool,
+ shape: &RawShape,
+ translation: &RawVector,
+ rotation: &RawRotation,
+ massPropsMode: u32,
+ mass: f32,
+ centerOfMass: &RawVector,
+ #[cfg(feature = "dim2")] principalAngularInertia: f32,
+ #[cfg(feature = "dim3")] principalAngularInertia: &RawVector,
+ #[cfg(feature = "dim3")] angularInertiaFrame: &RawRotation,
+ density: f32,
+ friction: f32,
+ restitution: f32,
+ frictionCombineRule: u32,
+ restitutionCombineRule: u32,
+ isSensor: bool,
+ collisionGroups: u32,
+ solverGroups: u32,
+ activeCollisionTypes: u16,
+ activeHooks: u32,
+ activeEvents: u32,
+ contactForceEventThreshold: f32,
+ contactSkin: f32,
+ hasParent: bool,
+ parent: FlatHandle,
+ bodies: &mut RawRigidBodySet,
+ ) -> Option {
+ let pos = Pose::from_parts(translation.0.into(), rotation.0);
+ let mut builder = ColliderBuilder::new(shape.0.clone())
+ .enabled(enabled)
+ .position(pos)
+ .friction(friction)
+ .restitution(restitution)
+ .collision_groups(super::unpack_interaction_groups(collisionGroups))
+ .solver_groups(super::unpack_interaction_groups(solverGroups))
+ .active_hooks(ActiveHooks::from_bits(activeHooks).unwrap_or(ActiveHooks::empty()))
+ .active_events(ActiveEvents::from_bits(activeEvents).unwrap_or(ActiveEvents::empty()))
+ .active_collision_types(
+ ActiveCollisionTypes::from_bits(activeCollisionTypes)
+ .unwrap_or(ActiveCollisionTypes::empty()),
+ )
+ .sensor(isSensor)
+ .friction_combine_rule(super::combine_rule_from_u32(frictionCombineRule))
+ .restitution_combine_rule(super::combine_rule_from_u32(restitutionCombineRule))
+ .contact_force_event_threshold(contactForceEventThreshold)
+ .contact_skin(contactSkin);
+
+ if massPropsMode == MassPropsMode::MassProps as u32 {
+ #[cfg(feature = "dim2")]
+ let mprops = MassProperties::new(centerOfMass.0.into(), mass, principalAngularInertia);
+ #[cfg(feature = "dim3")]
+ let mprops = MassProperties::with_principal_inertia_frame(
+ centerOfMass.0.into(),
+ mass,
+ principalAngularInertia.0,
+ angularInertiaFrame.0,
+ );
+ builder = builder.mass_properties(mprops);
+ } else if massPropsMode == MassPropsMode::Density as u32 {
+ builder = builder.density(density);
+ } else {
+ assert_eq!(massPropsMode, MassPropsMode::Mass as u32);
+ builder = builder.mass(mass);
+ };
+
+ let collider = builder.build();
+
+ if hasParent {
+ Some(utils::flat_handle(
+ self.0
+ .insert_with_parent(collider, utils::body_handle(parent), &mut bodies.0)
+ .0,
+ ))
+ } else {
+ Some(utils::flat_handle(self.0.insert(collider).0))
+ }
+ }
+}
+
+#[wasm_bindgen]
+impl RawColliderSet {
+ #[wasm_bindgen(constructor)]
+ pub fn new() -> Self {
+ RawColliderSet(ColliderSet::new())
+ }
+
+ pub fn len(&self) -> usize {
+ self.0.len()
+ }
+
+ pub fn contains(&self, handle: FlatHandle) -> bool {
+ self.0.get(utils::collider_handle(handle)).is_some()
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn createCollider(
+ &mut self,
+ enabled: bool,
+ shape: &RawShape,
+ translation: &RawVector,
+ rotation: &RawRotation,
+ massPropsMode: u32,
+ mass: f32,
+ centerOfMass: &RawVector,
+ principalAngularInertia: f32,
+ density: f32,
+ friction: f32,
+ restitution: f32,
+ frictionCombineRule: u32,
+ restitutionCombineRule: u32,
+ isSensor: bool,
+ collisionGroups: u32,
+ solverGroups: u32,
+ activeCollisionTypes: u16,
+ activeHooks: u32,
+ activeEvents: u32,
+ contactForceEventThreshold: f32,
+ contactSkin: f32,
+ hasParent: bool,
+ parent: FlatHandle,
+ bodies: &mut RawRigidBodySet,
+ ) -> Option {
+ self.do_create_collider(
+ enabled,
+ shape,
+ translation,
+ rotation,
+ massPropsMode,
+ mass,
+ centerOfMass,
+ principalAngularInertia,
+ density,
+ friction,
+ restitution,
+ frictionCombineRule,
+ restitutionCombineRule,
+ isSensor,
+ collisionGroups,
+ solverGroups,
+ activeCollisionTypes,
+ activeHooks,
+ activeEvents,
+ contactForceEventThreshold,
+ contactSkin,
+ hasParent,
+ parent,
+ bodies,
+ )
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn createCollider(
+ &mut self,
+ enabled: bool,
+ shape: &RawShape,
+ translation: &RawVector,
+ rotation: &RawRotation,
+ massPropsMode: u32,
+ mass: f32,
+ centerOfMass: &RawVector,
+ principalAngularInertia: &RawVector,
+ angularInertiaFrame: &RawRotation,
+ density: f32,
+ friction: f32,
+ restitution: f32,
+ frictionCombineRule: u32,
+ restitutionCombineRule: u32,
+ isSensor: bool,
+ collisionGroups: u32,
+ solverGroups: u32,
+ activeCollisionTypes: u16,
+ activeHooks: u32,
+ activeEvents: u32,
+ contactForceEventThreshold: f32,
+ contactSkin: f32,
+ hasParent: bool,
+ parent: FlatHandle,
+ bodies: &mut RawRigidBodySet,
+ ) -> Option {
+ self.do_create_collider(
+ enabled,
+ shape,
+ translation,
+ rotation,
+ massPropsMode,
+ mass,
+ centerOfMass,
+ principalAngularInertia,
+ angularInertiaFrame,
+ density,
+ friction,
+ restitution,
+ frictionCombineRule,
+ restitutionCombineRule,
+ isSensor,
+ collisionGroups,
+ solverGroups,
+ activeCollisionTypes,
+ activeHooks,
+ activeEvents,
+ contactForceEventThreshold,
+ contactSkin,
+ hasParent,
+ parent,
+ bodies,
+ )
+ }
+
+ /// Removes a collider from this set and wake-up the rigid-body it is attached to.
+ pub fn remove(
+ &mut self,
+ handle: FlatHandle,
+ islands: &mut RawIslandManager,
+ bodies: &mut RawRigidBodySet,
+ wakeUp: bool,
+ ) {
+ let handle = utils::collider_handle(handle);
+ self.0.remove(handle, &mut islands.0, &mut bodies.0, wakeUp);
+ }
+
+ /// Checks if a collider with the given integer handle exists.
+ pub fn isHandleValid(&self, handle: FlatHandle) -> bool {
+ self.0.get(utils::collider_handle(handle)).is_some()
+ }
+
+ /// Applies the given JavaScript function to the integer handle of each collider managed by this collider set.
+ ///
+ /// # Parameters
+ /// - `f(handle)`: the function to apply to the integer handle of each collider managed by this collider set. Called as `f(handle)`.
+ pub fn forEachColliderHandle(&self, f: &js_sys::Function) {
+ let this = JsValue::null();
+ for (handle, _) in self.0.iter() {
+ let _ = f.call1(&this, &JsValue::from(utils::flat_handle(handle.0)));
+ }
+ }
+}
diff --git a/typescript/src/geometry/contact.rs b/typescript/src/geometry/contact.rs
new file mode 100644
index 000000000..5acd09a5b
--- /dev/null
+++ b/typescript/src/geometry/contact.rs
@@ -0,0 +1,54 @@
+use rapier::parry::query;
+use wasm_bindgen::prelude::*;
+
+#[wasm_bindgen]
+pub struct RawShapeContact {
+ pub(crate) contact: query::Contact,
+}
+
+#[wasm_bindgen]
+impl RawShapeContact {
+ /// Writes the contact components into the given scratch buffer.
+ ///
+ /// Layout: `[distance, point1, point2, normal1, normal2]`.
+ #[cfg(feature = "dim2")]
+ pub fn getComponents(&self, scratch_buffer: &js_sys::Float32Array) {
+ scratch_buffer.set_index(0, self.contact.dist);
+ let p1 = self.contact.point1;
+ scratch_buffer.set_index(1, p1.x);
+ scratch_buffer.set_index(2, p1.y);
+ let p2 = self.contact.point2;
+ scratch_buffer.set_index(3, p2.x);
+ scratch_buffer.set_index(4, p2.y);
+ let n1 = self.contact.normal1;
+ scratch_buffer.set_index(5, n1.x);
+ scratch_buffer.set_index(6, n1.y);
+ let n2 = self.contact.normal2;
+ scratch_buffer.set_index(7, n2.x);
+ scratch_buffer.set_index(8, n2.y);
+ }
+
+ /// Writes the contact components into the given scratch buffer.
+ ///
+ /// Layout: `[distance, point1, point2, normal1, normal2]`.
+ #[cfg(feature = "dim3")]
+ pub fn getComponents(&self, scratch_buffer: &js_sys::Float32Array) {
+ scratch_buffer.set_index(0, self.contact.dist);
+ let p1 = self.contact.point1;
+ scratch_buffer.set_index(1, p1.x);
+ scratch_buffer.set_index(2, p1.y);
+ scratch_buffer.set_index(3, p1.z);
+ let p2 = self.contact.point2;
+ scratch_buffer.set_index(4, p2.x);
+ scratch_buffer.set_index(5, p2.y);
+ scratch_buffer.set_index(6, p2.z);
+ let n1 = self.contact.normal1;
+ scratch_buffer.set_index(7, n1.x);
+ scratch_buffer.set_index(8, n1.y);
+ scratch_buffer.set_index(9, n1.z);
+ let n2 = self.contact.normal2;
+ scratch_buffer.set_index(10, n2.x);
+ scratch_buffer.set_index(11, n2.y);
+ scratch_buffer.set_index(12, n2.z);
+ }
+}
diff --git a/typescript/src/geometry/feature.rs b/typescript/src/geometry/feature.rs
new file mode 100644
index 000000000..96e8f5114
--- /dev/null
+++ b/typescript/src/geometry/feature.rs
@@ -0,0 +1,47 @@
+use rapier::prelude::FeatureId;
+use wasm_bindgen::prelude::wasm_bindgen;
+
+#[cfg(feature = "dim2")]
+#[wasm_bindgen]
+#[derive(Copy, Clone)]
+pub enum RawFeatureType {
+ Vertex,
+ Face,
+ Unknown,
+}
+
+#[cfg(feature = "dim3")]
+#[wasm_bindgen]
+#[derive(Copy, Clone)]
+pub enum RawFeatureType {
+ Vertex,
+ Edge,
+ Face,
+ Unknown,
+}
+
+pub trait IntoTypeValue {
+ fn into_type(self) -> RawFeatureType;
+ fn into_value(self) -> Option;
+}
+
+impl IntoTypeValue for FeatureId {
+ fn into_type(self) -> RawFeatureType {
+ match self {
+ FeatureId::Vertex(_) => RawFeatureType::Vertex,
+ #[cfg(feature = "dim3")]
+ FeatureId::Edge(_) => RawFeatureType::Edge,
+ FeatureId::Face(_) => RawFeatureType::Face,
+ _ => RawFeatureType::Unknown,
+ }
+ }
+
+ fn into_value(self) -> Option {
+ match self {
+ FeatureId::Vertex(id) | FeatureId::Face(id) => Some(id),
+ #[cfg(feature = "dim3")]
+ FeatureId::Edge(id) => Some(id),
+ _ => None,
+ }
+ }
+}
diff --git a/typescript/src/geometry/mod.rs b/typescript/src/geometry/mod.rs
new file mode 100644
index 000000000..4f398d921
--- /dev/null
+++ b/typescript/src/geometry/mod.rs
@@ -0,0 +1,50 @@
+//! Structures related to geometry: colliders, shapes, etc.
+
+pub use self::broad_phase::*;
+pub use self::collider_set::*;
+pub use self::contact::*;
+pub use self::feature::*;
+pub use self::narrow_phase::*;
+pub use self::point::*;
+pub use self::ray::*;
+pub use self::shape::*;
+pub use self::toi::*;
+
+mod broad_phase;
+mod collider;
+mod collider_set;
+mod contact;
+mod feature;
+mod narrow_phase;
+mod point;
+mod ray;
+mod shape;
+mod toi;
+
+use rapier::dynamics::CoefficientCombineRule;
+use rapier::geometry::{InteractionGroups, InteractionTestMode};
+use rapier::prelude::Group;
+
+pub const fn unpack_interaction_groups(memberships_filter: u32) -> InteractionGroups {
+ InteractionGroups::new(
+ Group::from_bits_retain((memberships_filter >> 16) as u32),
+ Group::from_bits_retain((memberships_filter & 0x0000_ffff) as u32),
+ InteractionTestMode::And,
+ )
+}
+
+pub const fn pack_interaction_groups(groups: InteractionGroups) -> u32 {
+ (groups.memberships.bits() << 16) | groups.filter.bits()
+}
+
+pub const fn combine_rule_from_u32(rule: u32) -> CoefficientCombineRule {
+ if rule == CoefficientCombineRule::Average as u32 {
+ CoefficientCombineRule::Average
+ } else if rule == CoefficientCombineRule::Min as u32 {
+ CoefficientCombineRule::Min
+ } else if rule == CoefficientCombineRule::Multiply as u32 {
+ CoefficientCombineRule::Multiply
+ } else {
+ CoefficientCombineRule::Max
+ }
+}
diff --git a/typescript/src/geometry/narrow_phase.rs b/typescript/src/geometry/narrow_phase.rs
new file mode 100644
index 000000000..874f950b4
--- /dev/null
+++ b/typescript/src/geometry/narrow_phase.rs
@@ -0,0 +1,334 @@
+use crate::utils::{self, FlatHandle};
+use rapier::geometry::{ContactManifold, ContactPair, NarrowPhase};
+use rapier::math::Real;
+use wasm_bindgen::prelude::*;
+
+#[wasm_bindgen]
+pub struct RawNarrowPhase(pub(crate) NarrowPhase);
+
+#[wasm_bindgen]
+impl RawNarrowPhase {
+ #[wasm_bindgen(constructor)]
+ pub fn new() -> Self {
+ RawNarrowPhase(NarrowPhase::new())
+ }
+
+ pub fn contact_pairs_with(&self, handle1: FlatHandle, f: js_sys::Function) {
+ let this = JsValue::null();
+ let handle1 = utils::collider_handle(handle1);
+ for pair in self.0.contact_pairs_with(handle1) {
+ let handle2 = if pair.collider1 == handle1 {
+ utils::flat_handle(pair.collider2.0)
+ } else {
+ utils::flat_handle(pair.collider1.0)
+ };
+
+ let _ = f.call1(&this, &JsValue::from(handle2));
+ }
+ }
+
+ pub fn contact_pair(&self, handle1: FlatHandle, handle2: FlatHandle) -> Option {
+ let handle1 = utils::collider_handle(handle1);
+ let handle2 = utils::collider_handle(handle2);
+ self.0
+ .contact_pair(handle1, handle2)
+ .map(|p| RawContactPair(p as *const ContactPair))
+ }
+
+ pub fn intersection_pairs_with(&self, handle1: FlatHandle, f: js_sys::Function) {
+ let this = JsValue::null();
+ let handle1 = utils::collider_handle(handle1);
+ for (h1, h2, inter) in self.0.intersection_pairs_with(handle1) {
+ if inter {
+ let handle2 = if h1 == handle1 {
+ utils::flat_handle(h2.0)
+ } else {
+ utils::flat_handle(h1.0)
+ };
+
+ let _ = f.call1(&this, &JsValue::from(handle2));
+ }
+ }
+ }
+
+ pub fn intersection_pair(&self, handle1: FlatHandle, handle2: FlatHandle) -> bool {
+ let handle1 = utils::collider_handle(handle1);
+ let handle2 = utils::collider_handle(handle2);
+ self.0.intersection_pair(handle1, handle2) == Some(true)
+ }
+}
+
+#[wasm_bindgen]
+pub struct RawContactPair(*const ContactPair);
+#[wasm_bindgen]
+pub struct RawContactManifold(*const ContactManifold);
+
+// SAFETY: the use of a raw pointer is very unsafe.
+// We need this because wasm-bindgen doesn't support
+// lifetimes. So for the moment, we have to make sure
+// that our TypeScript wrapper properly free the pair
+// before the user has a chance to invalidate this pointer.
+#[wasm_bindgen]
+impl RawContactPair {
+ pub fn collider1(&self) -> FlatHandle {
+ unsafe { utils::flat_handle((*self.0).collider1.0) }
+ }
+
+ pub fn collider2(&self) -> FlatHandle {
+ unsafe { utils::flat_handle((*self.0).collider2.0) }
+ }
+
+ pub fn numContactManifolds(&self) -> usize {
+ unsafe { (*self.0).manifolds.len() }
+ }
+ pub fn contactManifold(&self, i: usize) -> Option {
+ unsafe {
+ (&(*self.0).manifolds)
+ .get(i)
+ .map(|m| RawContactManifold(m as *const ContactManifold))
+ }
+ }
+}
+
+#[wasm_bindgen]
+impl RawContactManifold {
+ #[cfg(feature = "dim2")]
+ pub fn normal(&self, scratch_buffer: &js_sys::Float32Array) {
+ unsafe {
+ let u = (*self.0).data.normal;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ }
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn normal(&self, scratch_buffer: &js_sys::Float32Array) {
+ unsafe {
+ let u = (*self.0).data.normal;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ }
+ }
+
+ // pub fn user_data(&self) -> u32 {
+ // unsafe { (*self.0).data.user_data }
+ // }
+
+ #[cfg(feature = "dim2")]
+ pub fn local_n1(&self, scratch_buffer: &js_sys::Float32Array) {
+ unsafe {
+ let u = (*self.0).local_n1;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ }
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn local_n1(&self, scratch_buffer: &js_sys::Float32Array) {
+ unsafe {
+ let u = (*self.0).local_n1;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ }
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn local_n2(&self, scratch_buffer: &js_sys::Float32Array) {
+ unsafe {
+ let u = (*self.0).local_n2;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ }
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn local_n2(&self, scratch_buffer: &js_sys::Float32Array) {
+ unsafe {
+ let u = (*self.0).local_n2;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ }
+ }
+
+ pub fn subshape1(&self) -> u32 {
+ unsafe { (*self.0).subshape1 }
+ }
+
+ pub fn subshape2(&self) -> u32 {
+ unsafe { (*self.0).subshape2 }
+ }
+
+ pub fn num_contacts(&self) -> usize {
+ unsafe { (*self.0).points.len() }
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn contact_local_p1(&self, i: usize, scratch_buffer: &js_sys::Float32Array) -> bool {
+ unsafe {
+ (&(*self.0).points).get(i).map_or(false, |c| {
+ let u = c.local_p1;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ true
+ })
+ }
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn contact_local_p1(&self, i: usize, scratch_buffer: &js_sys::Float32Array) -> bool {
+ unsafe {
+ (&(*self.0).points).get(i).map_or(false, |c| {
+ let u = c.local_p1;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ true
+ })
+ }
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn contact_local_p2(&self, i: usize, scratch_buffer: &js_sys::Float32Array) -> bool {
+ unsafe {
+ (&(*self.0).points).get(i).map_or(false, |c| {
+ let u = c.local_p2;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ true
+ })
+ }
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn contact_local_p2(&self, i: usize, scratch_buffer: &js_sys::Float32Array) -> bool {
+ unsafe {
+ (&(*self.0).points).get(i).map_or(false, |c| {
+ let u = c.local_p2;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ true
+ })
+ }
+ }
+
+ pub fn contact_dist(&self, i: usize) -> Real {
+ unsafe { (&(*self.0).points).get(i).map(|c| c.dist).unwrap_or(0.0) }
+ }
+
+ pub fn contact_fid1(&self, i: usize) -> u32 {
+ unsafe { (&(*self.0).points).get(i).map(|c| c.fid1.0).unwrap_or(0) }
+ }
+
+ pub fn contact_fid2(&self, i: usize) -> u32 {
+ unsafe { (&(*self.0).points).get(i).map(|c| c.fid2.0).unwrap_or(0) }
+ }
+
+ pub fn contact_impulse(&self, i: usize) -> Real {
+ unsafe {
+ (&(*self.0).points)
+ .get(i)
+ .map(|c| c.data.impulse)
+ .unwrap_or(0.0)
+ }
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn contact_tangent_impulse(&self, i: usize) -> Real {
+ unsafe {
+ (&(*self.0).points)
+ .get(i)
+ .map(|c| c.data.tangent_impulse.x)
+ .unwrap_or(0.0)
+ }
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn contact_tangent_impulse_x(&self, i: usize) -> Real {
+ unsafe {
+ (&(*self.0).points)
+ .get(i)
+ .map(|c| c.data.tangent_impulse.x)
+ .unwrap_or(0.0)
+ }
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn contact_tangent_impulse_y(&self, i: usize) -> Real {
+ unsafe {
+ (&(*self.0).points)
+ .get(i)
+ .map(|c| c.data.tangent_impulse.y)
+ .unwrap_or(0.0)
+ }
+ }
+
+ pub fn num_solver_contacts(&self) -> usize {
+ unsafe { (*self.0).data.solver_contacts.len() }
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn solver_contact_point(&self, i: usize, scratch_buffer: &js_sys::Float32Array) -> bool {
+ unsafe {
+ (&(*self.0).data).solver_contacts.get(i).map_or(false, |c| {
+ let u = c.point;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ true
+ })
+ }
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn solver_contact_point(&self, i: usize, scratch_buffer: &js_sys::Float32Array) -> bool {
+ unsafe {
+ (&(*self.0).data).solver_contacts.get(i).map_or(false, |c| {
+ let u = c.point;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ true
+ })
+ }
+ }
+
+ pub fn solver_contact_dist(&self, i: usize) -> Real {
+ unsafe {
+ (&(*self.0).data)
+ .solver_contacts
+ .get(i)
+ .map(|c| c.dist)
+ .unwrap_or(0.0)
+ }
+ }
+
+ pub fn solver_contact_friction(&self, i: usize) -> Real {
+ unsafe { (&(*self.0).data).solver_contacts[i].friction }
+ }
+
+ pub fn solver_contact_restitution(&self, i: usize) -> Real {
+ unsafe { (&(*self.0).data).solver_contacts[i].restitution }
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn solver_contact_tangent_velocity(&self, i: usize, scratch_buffer: &js_sys::Float32Array) {
+ unsafe {
+ let u = (&(*self.0).data).solver_contacts[i].tangent_velocity;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ }
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn solver_contact_tangent_velocity(&self, i: usize, scratch_buffer: &js_sys::Float32Array) {
+ unsafe {
+ let u = (&(*self.0).data).solver_contacts[i].tangent_velocity;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ }
+ }
+}
diff --git a/typescript/src/geometry/point.rs b/typescript/src/geometry/point.rs
new file mode 100644
index 000000000..a9c6ed823
--- /dev/null
+++ b/typescript/src/geometry/point.rs
@@ -0,0 +1,78 @@
+use crate::geometry::feature::IntoTypeValue;
+use crate::geometry::RawFeatureType;
+use crate::utils::{self, FlatHandle};
+use rapier::{
+ geometry::{ColliderHandle, PointProjection},
+ prelude::FeatureId,
+};
+use wasm_bindgen::prelude::*;
+
+#[wasm_bindgen]
+pub struct RawPointProjection(pub(crate) PointProjection);
+
+#[wasm_bindgen]
+impl RawPointProjection {
+ /// Writes the projected point components into the given scratch buffer.
+ #[cfg(feature = "dim2")]
+ pub fn point(&self, scratch_buffer: &js_sys::Float32Array) {
+ let u = self.0.point;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ }
+
+ /// Writes the projected point components into the given scratch buffer.
+ #[cfg(feature = "dim3")]
+ pub fn point(&self, scratch_buffer: &js_sys::Float32Array) {
+ let u = self.0.point;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ }
+
+ pub fn isInside(&self) -> bool {
+ self.0.is_inside
+ }
+}
+
+#[wasm_bindgen]
+pub struct RawPointColliderProjection {
+ pub(crate) handle: ColliderHandle,
+ pub(crate) proj: PointProjection,
+ pub(crate) feature: FeatureId,
+}
+
+#[wasm_bindgen]
+impl RawPointColliderProjection {
+ pub fn colliderHandle(&self) -> FlatHandle {
+ utils::flat_handle(self.handle.0)
+ }
+
+ /// Writes the projected point components into the given scratch buffer.
+ #[cfg(feature = "dim2")]
+ pub fn point(&self, scratch_buffer: &js_sys::Float32Array) {
+ let u = self.proj.point;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ }
+
+ /// Writes the projected point components into the given scratch buffer.
+ #[cfg(feature = "dim3")]
+ pub fn point(&self, scratch_buffer: &js_sys::Float32Array) {
+ let u = self.proj.point;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ }
+
+ pub fn isInside(&self) -> bool {
+ self.proj.is_inside
+ }
+
+ pub fn featureType(&self) -> RawFeatureType {
+ self.feature.into_type()
+ }
+
+ pub fn featureId(&self) -> Option {
+ self.feature.into_value()
+ }
+}
diff --git a/typescript/src/geometry/ray.rs b/typescript/src/geometry/ray.rs
new file mode 100644
index 000000000..a99723cc0
--- /dev/null
+++ b/typescript/src/geometry/ray.rs
@@ -0,0 +1,99 @@
+use crate::geometry::feature::IntoTypeValue;
+use crate::geometry::RawFeatureType;
+use crate::utils::{self, FlatHandle};
+use rapier::geometry::{ColliderHandle, RayIntersection};
+use wasm_bindgen::prelude::*;
+
+#[wasm_bindgen]
+pub struct RawRayIntersection(pub(crate) RayIntersection);
+
+#[wasm_bindgen]
+impl RawRayIntersection {
+ /// Writes the hit normal components into the given scratch buffer.
+ #[cfg(feature = "dim2")]
+ pub fn normal(&self, scratch_buffer: &js_sys::Float32Array) {
+ let u = self.0.normal;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ }
+
+ /// Writes the hit normal components into the given scratch buffer.
+ #[cfg(feature = "dim3")]
+ pub fn normal(&self, scratch_buffer: &js_sys::Float32Array) {
+ let u = self.0.normal;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ }
+
+ pub fn time_of_impact(&self) -> f32 {
+ self.0.time_of_impact
+ }
+
+ pub fn featureType(&self) -> RawFeatureType {
+ self.0.feature.into_type()
+ }
+
+ pub fn featureId(&self) -> Option {
+ self.0.feature.into_value()
+ }
+}
+
+#[wasm_bindgen]
+pub struct RawRayColliderIntersection {
+ pub(crate) handle: ColliderHandle,
+ pub(crate) inter: RayIntersection,
+}
+
+#[wasm_bindgen]
+impl RawRayColliderIntersection {
+ pub fn colliderHandle(&self) -> FlatHandle {
+ utils::flat_handle(self.handle.0)
+ }
+
+ /// Writes the hit normal components into the given scratch buffer.
+ #[cfg(feature = "dim2")]
+ pub fn normal(&self, scratch_buffer: &js_sys::Float32Array) {
+ let u = self.inter.normal;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ }
+
+ /// Writes the hit normal components into the given scratch buffer.
+ #[cfg(feature = "dim3")]
+ pub fn normal(&self, scratch_buffer: &js_sys::Float32Array) {
+ let u = self.inter.normal;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ scratch_buffer.set_index(2, u.z);
+ }
+
+ pub fn time_of_impact(&self) -> f32 {
+ self.inter.time_of_impact
+ }
+
+ pub fn featureType(&self) -> RawFeatureType {
+ self.inter.feature.into_type()
+ }
+
+ pub fn featureId(&self) -> Option {
+ self.inter.feature.into_value()
+ }
+}
+
+#[wasm_bindgen]
+pub struct RawRayColliderHit {
+ pub(crate) handle: ColliderHandle,
+ pub(crate) timeOfImpact: f32,
+}
+
+#[wasm_bindgen]
+impl RawRayColliderHit {
+ pub fn colliderHandle(&self) -> FlatHandle {
+ utils::flat_handle(self.handle.0)
+ }
+
+ pub fn timeOfImpact(&self) -> f32 {
+ self.timeOfImpact
+ }
+}
diff --git a/typescript/src/geometry/shape.rs b/typescript/src/geometry/shape.rs
new file mode 100644
index 000000000..c6463feca
--- /dev/null
+++ b/typescript/src/geometry/shape.rs
@@ -0,0 +1,1331 @@
+use crate::geometry::{RawPointProjection, RawRayIntersection, RawShapeCastHit, RawShapeContact};
+use crate::math::{RawRotation, RawVector};
+use rapier::geometry::{Shape, SharedShape, TriMeshFlags};
+use rapier::math::{IVector, Pose, Rotation, Vector, DIM};
+#[cfg(feature = "dim3")]
+use rapier::parry::utils::Array2;
+use rapier::parry::query;
+use rapier::parry::query::{Ray, ShapeCastOptions};
+use rapier::parry::transformation::vhacd::{VHACDParameters, VHACD};
+use wasm_bindgen::prelude::*;
+
+pub trait SharedShapeUtility {
+ fn castShape(
+ &self,
+ shapePos1: &Pose,
+ shapeVel1: &Vector,
+ shape2: &dyn Shape,
+ shapePos2: &Pose,
+ shapeVel2: &Vector,
+ target_distance: f32,
+ maxToi: f32,
+ stop_at_penetration: bool,
+ ) -> Option;
+
+ fn intersectsShape(
+ &self,
+ shapePos1: &Pose,
+ shape2: &dyn Shape,
+ shapePos2: &Pose,
+ ) -> bool;
+
+ fn contactShape(
+ &self,
+ shapePos1: &Pose,
+ shape2: &dyn Shape,
+ shapePos2: &Pose,
+ prediction: f32,
+ ) -> Option;
+
+ fn containsPoint(&self, shapePos: &Pose, point: &Vector) -> bool;
+
+ fn projectPoint(
+ &self,
+ shapePos: &Pose,
+ point: &Vector,
+ solid: bool,
+ ) -> RawPointProjection;
+
+ fn intersectsRay(
+ &self,
+ shapePos: &Pose,
+ rayOrig: Vector,
+ rayDir: Vector,
+ maxToi: f32,
+ ) -> bool;
+
+ fn castRay(
+ &self,
+ shapePos: &Pose,
+ rayOrig: Vector,
+ rayDir: Vector,
+ maxToi: f32,
+ solid: bool,
+ ) -> f32;
+
+ fn castRayAndGetNormal(
+ &self,
+ shapePos: &Pose,
+ rayOrig: Vector,
+ rayDir: Vector,
+ maxToi: f32,
+ solid: bool,
+ ) -> Option;
+}
+
+#[cfg(feature = "dim3")]
+pub(crate) fn normalized_convex_polyhedron_mesh(
+ polyhedron: &rapier::parry::shape::ConvexPolyhedron,
+) -> Option<(Vec, Vec)> {
+ let (points, indices) =
+ rapier::parry::transformation::try_convex_hull(polyhedron.points()).ok()?;
+ let flat_indices = indices
+ .iter()
+ .flat_map(|triangle| triangle.iter())
+ .copied()
+ .collect();
+ Some((points, flat_indices))
+}
+
+// for RawShape & Collider
+impl SharedShapeUtility for SharedShape {
+ fn castShape(
+ &self,
+ shapePos1: &Pose,
+ shapeVel1: &Vector,
+ shape2: &dyn Shape,
+ shapePos2: &Pose,
+ shapeVel2: &Vector,
+ target_distance: f32,
+ maxToi: f32,
+ stop_at_penetration: bool,
+ ) -> Option {
+ query::cast_shapes(
+ shapePos1,
+ *shapeVel1,
+ &*self.0,
+ shapePos2,
+ *shapeVel2,
+ shape2,
+ ShapeCastOptions {
+ max_time_of_impact: maxToi,
+ target_distance,
+ stop_at_penetration,
+ compute_impact_geometry_on_penetration: true,
+ },
+ )
+ .ok()
+ .flatten()
+ .map(|hit| RawShapeCastHit { hit })
+ }
+
+ fn intersectsShape(
+ &self,
+ shapePos1: &Pose,
+ shape2: &dyn Shape,
+ shapePos2: &Pose,
+ ) -> bool {
+ query::intersection_test(shapePos1, &*self.0, shapePos2, shape2).unwrap_or(false)
+ }
+
+ fn contactShape(
+ &self,
+ shapePos1: &Pose,
+ shape2: &dyn Shape,
+ shapePos2: &Pose,
+ prediction: f32,
+ ) -> Option {
+ query::contact(shapePos1, &*self.0, shapePos2, shape2, prediction)
+ .ok()
+ .flatten()
+ .map(|contact| RawShapeContact { contact })
+ }
+
+ fn containsPoint(&self, shapePos: &Pose, point: &Vector) -> bool {
+ self.as_ref().contains_point(shapePos, *point)
+ }
+
+ fn projectPoint(
+ &self,
+ shapePos: &Pose,
+ point: &Vector,
+ solid: bool,
+ ) -> RawPointProjection {
+ RawPointProjection(self.as_ref().project_point(shapePos, *point, solid))
+ }
+
+ fn intersectsRay(
+ &self,
+ shapePos: &Pose,
+ rayOrig: Vector,
+ rayDir: Vector,
+ maxToi: f32,
+ ) -> bool {
+ self.as_ref()
+ .intersects_ray(shapePos, &Ray::new(rayOrig, rayDir), maxToi)
+ }
+
+ fn castRay(
+ &self,
+ shapePos: &Pose,
+ rayOrig: Vector,
+ rayDir: Vector,
+ maxToi: f32,
+ solid: bool,
+ ) -> f32 {
+ self.as_ref()
+ .cast_ray(shapePos, &Ray::new(rayOrig, rayDir), maxToi, solid)
+ .unwrap_or(-1.0) // Negative value = no hit.
+ }
+
+ fn castRayAndGetNormal(
+ &self,
+ shapePos: &Pose,
+ rayOrig: Vector,
+ rayDir: Vector,
+ maxToi: f32,
+ solid: bool,
+ ) -> Option {
+ self.as_ref()
+ .cast_ray_and_get_normal(shapePos, &Ray::new(rayOrig, rayDir), maxToi, solid)
+ .map(|inter| RawRayIntersection(inter))
+ }
+}
+
+#[wasm_bindgen]
+#[cfg(feature = "dim2")]
+pub enum RawShapeType {
+ Ball = 0,
+ Cuboid = 1,
+ Capsule = 2,
+ Segment = 3,
+ Polyline = 4,
+ Triangle = 5,
+ TriMesh = 6,
+ HeightField = 7,
+ Compound = 8,
+ ConvexPolygon = 9,
+ RoundCuboid = 10,
+ RoundTriangle = 11,
+ RoundConvexPolygon = 12,
+ HalfSpace = 13,
+ Voxels = 14,
+}
+
+#[wasm_bindgen]
+#[cfg(feature = "dim3")]
+pub enum RawShapeType {
+ Ball = 0,
+ Cuboid = 1,
+ Capsule = 2,
+ Segment = 3,
+ Polyline = 4,
+ Triangle = 5,
+ TriMesh = 6,
+ HeightField = 7,
+ Compound = 8,
+ ConvexPolyhedron = 9,
+ Cylinder = 10,
+ Cone = 11,
+ RoundCuboid = 12,
+ RoundTriangle = 13,
+ RoundCylinder = 14,
+ RoundCone = 15,
+ RoundConvexPolyhedron = 16,
+ HalfSpace = 17,
+ Voxels = 18,
+}
+
+/// Parameters for VHACD convex decomposition algorithm
+#[wasm_bindgen]
+pub struct RawVHACDParameters(pub(crate) VHACDParameters);
+
+#[wasm_bindgen]
+impl RawVHACDParameters {
+ #[wasm_bindgen(constructor)]
+ pub fn new() -> Self {
+ RawVHACDParameters(VHACDParameters::default())
+ }
+
+ #[wasm_bindgen(getter)]
+ pub fn alpha(&self) -> f32 {
+ self.0.alpha
+ }
+ #[wasm_bindgen(setter)]
+ pub fn set_alpha(&mut self, val: f32) {
+ self.0.alpha = val.clamp(0.0, 1.0);
+ }
+
+ #[wasm_bindgen(getter)]
+ pub fn beta(&self) -> f32 {
+ self.0.beta
+ }
+ #[wasm_bindgen(setter)]
+ pub fn set_beta(&mut self, val: f32) {
+ self.0.beta = val.clamp(0.0, 1.0);
+ }
+
+ #[wasm_bindgen(getter)]
+ pub fn concavity(&self) -> f32 {
+ self.0.concavity
+ }
+ #[wasm_bindgen(setter)]
+ pub fn set_concavity(&mut self, val: f32) {
+ self.0.concavity = val.clamp(0.0, 1.0);
+ }
+
+ #[wasm_bindgen(getter)]
+ pub fn plane_downsampling(&self) -> u32 {
+ self.0.plane_downsampling
+ }
+ #[wasm_bindgen(setter)]
+ pub fn set_plane_downsampling(&mut self, val: u32) {
+ self.0.plane_downsampling = val;
+ }
+
+ #[wasm_bindgen(getter)]
+ pub fn convex_hull_downsampling(&self) -> u32 {
+ self.0.convex_hull_downsampling
+ }
+ #[wasm_bindgen(setter)]
+ pub fn set_convex_hull_downsampling(&mut self, val: u32) {
+ self.0.convex_hull_downsampling = val;
+ }
+
+ #[wasm_bindgen(getter)]
+ pub fn max_convex_hulls(&self) -> u32 {
+ self.0.max_convex_hulls
+ }
+ #[wasm_bindgen(setter)]
+ pub fn set_max_convex_hulls(&mut self, val: u32) {
+ self.0.max_convex_hulls = val;
+ }
+
+ #[wasm_bindgen(getter)]
+ pub fn resolution(&self) -> u32 {
+ self.0.resolution
+ }
+ #[wasm_bindgen(setter)]
+ pub fn set_resolution(&mut self, val: u32) {
+ self.0.resolution = val;
+ }
+
+ #[wasm_bindgen(getter)]
+ pub fn convex_hull_approximation(&self) -> bool {
+ self.0.convex_hull_approximation
+ }
+ #[wasm_bindgen(setter)]
+ pub fn set_convex_hull_approximation(&mut self, val: bool) {
+ self.0.convex_hull_approximation = val;
+ }
+}
+
+/// The vertex/index buffers of a convex polyhedron’s convex hull.
+#[cfg(feature = "dim3")]
+#[wasm_bindgen(getter_with_clone)]
+pub struct RawConvexMeshData {
+ pub vertices: Vec,
+ pub indices: Vec,
+}
+
+#[wasm_bindgen]
+pub struct RawShape(pub(crate) SharedShape);
+
+#[wasm_bindgen]
+impl RawShape {
+ pub fn shapeType(&self) -> RawShapeType {
+ match self.0.shape_type() {
+ rapier::geometry::ShapeType::Ball => RawShapeType::Ball,
+ rapier::geometry::ShapeType::Cuboid => RawShapeType::Cuboid,
+ rapier::geometry::ShapeType::Capsule => RawShapeType::Capsule,
+ rapier::geometry::ShapeType::Segment => RawShapeType::Segment,
+ rapier::geometry::ShapeType::Polyline => RawShapeType::Polyline,
+ rapier::geometry::ShapeType::Triangle => RawShapeType::Triangle,
+ rapier::geometry::ShapeType::TriMesh => RawShapeType::TriMesh,
+ rapier::geometry::ShapeType::HeightField => RawShapeType::HeightField,
+ rapier::geometry::ShapeType::Compound => RawShapeType::Compound,
+ rapier::geometry::ShapeType::HalfSpace => RawShapeType::HalfSpace,
+ rapier::geometry::ShapeType::Voxels => RawShapeType::Voxels,
+ #[cfg(feature = "dim3")]
+ rapier::geometry::ShapeType::ConvexPolyhedron => RawShapeType::ConvexPolyhedron,
+ #[cfg(feature = "dim2")]
+ rapier::geometry::ShapeType::ConvexPolygon => RawShapeType::ConvexPolygon,
+ #[cfg(feature = "dim3")]
+ rapier::geometry::ShapeType::Cylinder => RawShapeType::Cylinder,
+ #[cfg(feature = "dim3")]
+ rapier::geometry::ShapeType::Cone => RawShapeType::Cone,
+ rapier::geometry::ShapeType::RoundCuboid => RawShapeType::RoundCuboid,
+ rapier::geometry::ShapeType::RoundTriangle => RawShapeType::RoundTriangle,
+ #[cfg(feature = "dim3")]
+ rapier::geometry::ShapeType::RoundCylinder => RawShapeType::RoundCylinder,
+ #[cfg(feature = "dim3")]
+ rapier::geometry::ShapeType::RoundCone => RawShapeType::RoundCone,
+ #[cfg(feature = "dim3")]
+ rapier::geometry::ShapeType::RoundConvexPolyhedron => {
+ RawShapeType::RoundConvexPolyhedron
+ }
+ #[cfg(feature = "dim2")]
+ rapier::geometry::ShapeType::RoundConvexPolygon => RawShapeType::RoundConvexPolygon,
+ rapier::geometry::ShapeType::Custom => panic!("Not yet implemented."),
+ }
+ }
+
+ pub fn halfspaceNormal(&self) -> Option {
+ self.0
+ .as_halfspace()
+ .map(|halfspace| halfspace.normal.into())
+ }
+
+ pub fn halfExtents(&self) -> Option {
+ self.0
+ .as_cuboid()
+ .map(|cuboid| cuboid.half_extents.into())
+ .or_else(|| {
+ self.0
+ .as_round_cuboid()
+ .map(|cuboid| cuboid.inner_shape.half_extents.into())
+ })
+ }
+
+ pub fn radius(&self) -> Option {
+ match self.0.shape_type() {
+ rapier::geometry::ShapeType::Ball => self.0.as_ball().map(|ball| ball.radius),
+ rapier::geometry::ShapeType::Capsule => {
+ self.0.as_capsule().map(|capsule| capsule.radius)
+ }
+ #[cfg(feature = "dim3")]
+ rapier::geometry::ShapeType::Cylinder => {
+ self.0.as_cylinder().map(|cylinder| cylinder.radius)
+ }
+ #[cfg(feature = "dim3")]
+ rapier::geometry::ShapeType::RoundCylinder => self
+ .0
+ .as_round_cylinder()
+ .map(|cylinder| cylinder.inner_shape.radius),
+ #[cfg(feature = "dim3")]
+ rapier::geometry::ShapeType::Cone => self.0.as_cone().map(|cone| cone.radius),
+ #[cfg(feature = "dim3")]
+ rapier::geometry::ShapeType::RoundCone => {
+ self.0.as_round_cone().map(|cone| cone.inner_shape.radius)
+ }
+ _ => None,
+ }
+ }
+
+ pub fn halfHeight(&self) -> Option {
+ match self.0.shape_type() {
+ rapier::geometry::ShapeType::Capsule => {
+ self.0.as_capsule().map(|capsule| capsule.half_height())
+ }
+ #[cfg(feature = "dim3")]
+ rapier::geometry::ShapeType::Cylinder => {
+ self.0.as_cylinder().map(|cylinder| cylinder.half_height)
+ }
+ #[cfg(feature = "dim3")]
+ rapier::geometry::ShapeType::RoundCylinder => self
+ .0
+ .as_round_cylinder()
+ .map(|cylinder| cylinder.inner_shape.half_height),
+ #[cfg(feature = "dim3")]
+ rapier::geometry::ShapeType::Cone => self.0.as_cone().map(|cone| cone.half_height),
+ #[cfg(feature = "dim3")]
+ rapier::geometry::ShapeType::RoundCone => self
+ .0
+ .as_round_cone()
+ .map(|cone| cone.inner_shape.half_height),
+ _ => None,
+ }
+ }
+
+ pub fn roundRadius(&self) -> Option {
+ match self.0.shape_type() {
+ rapier::geometry::ShapeType::RoundCuboid => {
+ self.0.as_round_cuboid().map(|cuboid| cuboid.border_radius)
+ }
+ rapier::geometry::ShapeType::RoundTriangle => self
+ .0
+ .as_round_triangle()
+ .map(|triangle| triangle.border_radius),
+ #[cfg(feature = "dim3")]
+ rapier::geometry::ShapeType::RoundCylinder => self
+ .0
+ .as_round_cylinder()
+ .map(|cylinder| cylinder.border_radius),
+ #[cfg(feature = "dim3")]
+ rapier::geometry::ShapeType::RoundCone => {
+ self.0.as_round_cone().map(|cone| cone.border_radius)
+ }
+ #[cfg(feature = "dim3")]
+ rapier::geometry::ShapeType::RoundConvexPolyhedron => self
+ .0
+ .as_round_convex_polyhedron()
+ .map(|polyhedron| polyhedron.border_radius),
+ #[cfg(feature = "dim2")]
+ rapier::geometry::ShapeType::RoundConvexPolygon => self
+ .0
+ .as_round_convex_polygon()
+ .map(|polygon| polygon.border_radius),
+ _ => None,
+ }
+ }
+
+ pub fn voxelData(&self) -> Option> {
+ let voxels = self.0.as_voxels()?;
+ Some(
+ voxels
+ .voxels()
+ .filter_map(|vox| (!vox.state.is_empty()).then_some(vox.grid_coords))
+ .flat_map(|ids| ids.to_array())
+ .collect(),
+ )
+ }
+
+ pub fn voxelSize(&self) -> Option {
+ self.0
+ .as_voxels()
+ .map(|voxels| RawVector(voxels.voxel_size()))
+ }
+
+ /// The vertices of this shape, if it is vertex-based.
+ ///
+ /// For convex polyhedra, this returns the vertices of a convex hull recomputed with
+ /// `try_convex_hull` (so they may differ in count and order from the points the shape
+ /// was built from), ensuring the result can be fed back to `RawShape::convexMesh`.
+ /// If both `vertices` and `indices` are needed, prefer `convexMeshData` which computes
+ /// the convex hull only once.
+ pub fn vertices(&self) -> Option> {
+ let flatten = |vertices: &[Vector]| {
+ vertices
+ .iter()
+ .flat_map(|point| point.to_array())
+ .collect()
+ };
+
+ match self.0.shape_type() {
+ rapier::geometry::ShapeType::TriMesh => {
+ self.0.as_trimesh().map(|mesh| flatten(mesh.vertices()))
+ }
+ #[cfg(feature = "dim2")]
+ rapier::geometry::ShapeType::Polyline => self
+ .0
+ .as_polyline()
+ .map(|polyline| flatten(polyline.vertices())),
+ #[cfg(feature = "dim3")]
+ rapier::geometry::ShapeType::ConvexPolyhedron => self
+ .0
+ .as_convex_polyhedron()
+ .and_then(normalized_convex_polyhedron_mesh)
+ .map(|(points, _)| flatten(&points)),
+ #[cfg(feature = "dim3")]
+ rapier::geometry::ShapeType::RoundConvexPolyhedron => self
+ .0
+ .as_round_convex_polyhedron()
+ .and_then(|polyhedron| normalized_convex_polyhedron_mesh(&polyhedron.inner_shape))
+ .map(|(points, _)| flatten(&points)),
+ #[cfg(feature = "dim2")]
+ rapier::geometry::ShapeType::ConvexPolygon => self
+ .0
+ .as_convex_polygon()
+ .map(|polygon| flatten(polygon.points())),
+ #[cfg(feature = "dim2")]
+ rapier::geometry::ShapeType::RoundConvexPolygon => self
+ .0
+ .as_round_convex_polygon()
+ .map(|polygon| flatten(polygon.inner_shape.points())),
+ rapier::geometry::ShapeType::Segment => self
+ .0
+ .as_segment()
+ .map(|segment| flatten(&[segment.a, segment.b])),
+ rapier::geometry::ShapeType::RoundTriangle => {
+ self.0.as_round_triangle().map(|triangle| {
+ flatten(&[
+ triangle.inner_shape.a,
+ triangle.inner_shape.b,
+ triangle.inner_shape.c,
+ ])
+ })
+ }
+ rapier::geometry::ShapeType::Triangle => self
+ .0
+ .as_triangle()
+ .map(|triangle| flatten(&[triangle.a, triangle.b, triangle.c])),
+ _ => None,
+ }
+ }
+
+ pub fn indices(&self) -> Option> {
+ match self.0.shape_type() {
+ rapier::geometry::ShapeType::TriMesh => self.0.as_trimesh().map(|mesh| {
+ mesh.indices()
+ .iter()
+ .flat_map(|triangle| triangle.iter())
+ .copied()
+ .collect()
+ }),
+ rapier::geometry::ShapeType::Polyline => self.0.as_polyline().map(|polyline| {
+ polyline
+ .indices()
+ .iter()
+ .flat_map(|segment| segment.iter())
+ .copied()
+ .collect()
+ }),
+ #[cfg(feature = "dim3")]
+ rapier::geometry::ShapeType::ConvexPolyhedron => self
+ .0
+ .as_convex_polyhedron()
+ .and_then(normalized_convex_polyhedron_mesh)
+ .map(|(_, indices)| indices),
+ #[cfg(feature = "dim3")]
+ rapier::geometry::ShapeType::RoundConvexPolyhedron => self
+ .0
+ .as_round_convex_polyhedron()
+ .and_then(|polyhedron| normalized_convex_polyhedron_mesh(&polyhedron.inner_shape))
+ .map(|(_, indices)| indices),
+ _ => None,
+ }
+ }
+
+ /// The vertices and indices of the convex hull of this convex polyhedron, recomputed
+ /// with `try_convex_hull` so that the result can always be fed back to
+ /// `RawShape::convexMesh`.
+ ///
+ /// This computes the convex hull only once, unlike calling both `vertices()` and
+ /// `indices()`.
+ #[cfg(feature = "dim3")]
+ pub fn convexMeshData(&self) -> Option {
+ let polyhedron = match self.0.shape_type() {
+ rapier::geometry::ShapeType::ConvexPolyhedron => self.0.as_convex_polyhedron(),
+ rapier::geometry::ShapeType::RoundConvexPolyhedron => self
+ .0
+ .as_round_convex_polyhedron()
+ .map(|polyhedron| &polyhedron.inner_shape),
+ _ => None,
+ }?;
+ let (points, indices) = normalized_convex_polyhedron_mesh(polyhedron)?;
+ Some(RawConvexMeshData {
+ vertices: points
+ .iter()
+ .flat_map(|point| point.to_array())
+ .collect(),
+ indices,
+ })
+ }
+
+ pub fn triMeshFlags(&self) -> Option {
+ self.0
+ .as_trimesh()
+ .map(|trimesh| trimesh.flags().bits() as u32)
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn heightFieldFlags(&self) -> Option {
+ self.0
+ .as_heightfield()
+ .map(|heightfield| heightfield.flags().bits() as u32)
+ }
+
+ pub fn heightfieldHeights(&self) -> Option> {
+ match self.0.shape_type() {
+ rapier::geometry::ShapeType::HeightField => self.0.as_heightfield().map(|heightfield| {
+ #[cfg(feature = "dim2")]
+ {
+ heightfield.heights().as_slice().to_vec()
+ }
+ #[cfg(feature = "dim3")]
+ {
+ heightfield.heights().data().to_vec()
+ }
+ }),
+ _ => None,
+ }
+ }
+
+ pub fn heightfieldScale(&self) -> Option {
+ match self.0.shape_type() {
+ rapier::geometry::ShapeType::HeightField => self
+ .0
+ .as_heightfield()
+ .map(|heightfield| RawVector(heightfield.scale())),
+ _ => None,
+ }
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn heightfieldNRows(&self) -> Option {
+ match self.0.shape_type() {
+ rapier::geometry::ShapeType::HeightField => self
+ .0
+ .as_heightfield()
+ .map(|heightfield| heightfield.nrows()),
+ _ => None,
+ }
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn heightfieldNCols(&self) -> Option {
+ match self.0.shape_type() {
+ rapier::geometry::ShapeType::HeightField => self
+ .0
+ .as_heightfield()
+ .map(|heightfield| heightfield.ncols()),
+ _ => None,
+ }
+ }
+
+ pub fn compoundLen(&self) -> Option {
+ self.0.as_compound().map(|compound| compound.shapes().len())
+ }
+
+ pub fn compoundShape(&self, index: usize) -> Option {
+ self.0
+ .as_compound()
+ .and_then(|compound| compound.shapes().get(index))
+ .map(|(_, shape)| RawShape(shape.clone()))
+ }
+
+ pub fn compoundTranslation(&self, index: usize) -> Option {
+ self.0
+ .as_compound()
+ .and_then(|compound| compound.shapes().get(index))
+ .map(|(position, _)| position.translation.into())
+ }
+
+ pub fn compoundRotation(&self, index: usize) -> Option {
+ self.0
+ .as_compound()
+ .and_then(|compound| compound.shapes().get(index))
+ .map(|(position, _)| position.rotation.into())
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn cuboid(hx: f32, hy: f32) -> Self {
+ Self(SharedShape::cuboid(hx, hy))
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn cuboid(hx: f32, hy: f32, hz: f32) -> Self {
+ Self(SharedShape::cuboid(hx, hy, hz))
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn roundCuboid(hx: f32, hy: f32, borderRadius: f32) -> Self {
+ Self(SharedShape::round_cuboid(hx, hy, borderRadius))
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn roundCuboid(hx: f32, hy: f32, hz: f32, borderRadius: f32) -> Self {
+ Self(SharedShape::round_cuboid(hx, hy, hz, borderRadius))
+ }
+
+ pub fn ball(radius: f32) -> Self {
+ Self(SharedShape::ball(radius))
+ }
+
+ pub fn halfspace(normal: &RawVector) -> Self {
+ Self(SharedShape::halfspace(normal.0.normalize()))
+ }
+
+ pub fn capsule(halfHeight: f32, radius: f32) -> Self {
+ let p2 = Vector::Y * halfHeight;
+ let p1 = -p2;
+ Self(SharedShape::capsule(p1, p2, radius))
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn cylinder(halfHeight: f32, radius: f32) -> Self {
+ Self(SharedShape::cylinder(halfHeight, radius))
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn roundCylinder(halfHeight: f32, radius: f32, borderRadius: f32) -> Self {
+ Self(SharedShape::round_cylinder(
+ halfHeight,
+ radius,
+ borderRadius,
+ ))
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn cone(halfHeight: f32, radius: f32) -> Self {
+ Self(SharedShape::cone(halfHeight, radius))
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn roundCone(halfHeight: f32, radius: f32, borderRadius: f32) -> Self {
+ Self(SharedShape::round_cone(halfHeight, radius, borderRadius))
+ }
+
+ pub fn voxels(voxel_size: &RawVector, grid_coords: Vec) -> Self {
+ let grid_coords: Vec<_> = grid_coords
+ .chunks_exact(DIM)
+ .map(IVector::from_slice)
+ .collect();
+ Self(SharedShape::voxels(voxel_size.0, &grid_coords))
+ }
+
+ pub fn voxelsFromPoints(voxel_size: &RawVector, points: Vec) -> Self {
+ let points: Vec<_> = points.chunks_exact(DIM).map(Vector::from_slice).collect();
+ Self(SharedShape::voxels_from_points(voxel_size.0, &points))
+ }
+
+ pub fn polyline(vertices: Vec, indices: Vec) -> Self {
+ let vertices = vertices.chunks(DIM).map(|v| Vector::from_slice(v)).collect();
+ let indices: Vec<_> = indices.chunks(2).map(|v| [v[0], v[1]]).collect();
+ if indices.is_empty() {
+ Self(SharedShape::polyline(vertices, None))
+ } else {
+ Self(SharedShape::polyline(vertices, Some(indices)))
+ }
+ }
+
+ pub fn trimesh(vertices: Vec, indices: Vec, flags: u32) -> Option {
+ let flags = TriMeshFlags::from_bits(flags as u16).unwrap_or_default();
+ let vertices = vertices.chunks(DIM).map(|v| Vector::from_slice(v)).collect();
+ let indices = indices.chunks(3).map(|v| [v[0], v[1], v[2]]).collect();
+ SharedShape::trimesh_with_flags(vertices, indices, flags)
+ .ok()
+ .map(Self)
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn heightfield(heights: Vec, scale: &RawVector) -> Self {
+ Self(SharedShape::heightfield(heights, scale.0))
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn heightfield(
+ nrows: u32,
+ ncols: u32,
+ heights: Vec,
+ scale: &RawVector,
+ flags: u32,
+ ) -> Self {
+ let flags =
+ rapier::parry::shape::HeightFieldFlags::from_bits(flags as u8).unwrap_or_default();
+ let heights = Array2::new(nrows as usize + 1, ncols as usize + 1, heights);
+ Self(SharedShape::heightfield_with_flags(heights, scale.0, flags))
+ }
+
+ pub fn segment(p1: &RawVector, p2: &RawVector) -> Self {
+ Self(SharedShape::segment(p1.0.into(), p2.0.into()))
+ }
+
+ pub fn triangle(p1: &RawVector, p2: &RawVector, p3: &RawVector) -> Self {
+ Self(SharedShape::triangle(p1.0.into(), p2.0.into(), p3.0.into()))
+ }
+
+ pub fn roundTriangle(
+ p1: &RawVector,
+ p2: &RawVector,
+ p3: &RawVector,
+ borderRadius: f32,
+ ) -> Self {
+ Self(SharedShape::round_triangle(
+ p1.0.into(),
+ p2.0.into(),
+ p3.0.into(),
+ borderRadius,
+ ))
+ }
+
+ pub fn convexHull(points: Vec) -> Option {
+ let points: Vec<_> = points.chunks(DIM).map(|v| Vector::from_slice(v)).collect();
+ SharedShape::convex_hull(&points).map(|s| Self(s))
+ }
+
+ pub fn roundConvexHull(points: Vec, borderRadius: f32) -> Option {
+ let points: Vec<_> = points.chunks(DIM).map(|v| Vector::from_slice(v)).collect();
+ SharedShape::round_convex_hull(&points, borderRadius).map(|s| Self(s))
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn convexPolyline(vertices: Vec) -> Option {
+ let vertices = vertices.chunks(DIM).map(|v| Vector::from_slice(v)).collect();
+ SharedShape::convex_polyline(vertices).map(|s| Self(s))
+ }
+
+ #[cfg(feature = "dim2")]
+ pub fn roundConvexPolyline(vertices: Vec, borderRadius: f32) -> Option {
+ let vertices = vertices.chunks(DIM).map(|v| Vector::from_slice(v)).collect();
+ SharedShape::round_convex_polyline(vertices, borderRadius).map(|s| Self(s))
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn convexMesh(vertices: Vec, indices: Vec) -> Option {
+ let vertices = vertices.chunks(DIM).map(|v| Vector::from_slice(v)).collect();
+ let indices: Vec<_> = indices.chunks(3).map(|v| [v[0], v[1], v[2]]).collect();
+ SharedShape::convex_mesh(vertices, &indices).map(|s| Self(s))
+ }
+
+ #[cfg(feature = "dim3")]
+ pub fn roundConvexMesh(
+ vertices: Vec,
+ indices: Vec,
+ borderRadius: f32,
+ ) -> Option {
+ let vertices = vertices.chunks(DIM).map(|v| Vector::from_slice(v)).collect();
+ let indices: Vec<_> = indices.chunks(3).map(|v| [v[0], v[1], v[2]]).collect();
+ SharedShape::round_convex_mesh(vertices, &indices, borderRadius).map(|s| Self(s))
+ }
+
+ pub fn compound(shapes: Vec, positions: Vec, rotations: Vec) -> RawShape {
+ let mut compound_parts = Vec::new();
+ let num_shapes = shapes.len();
+
+ assert_eq!(
+ positions.len(),
+ num_shapes * DIM,
+ "The compound positions array must contain DIM entries per shape."
+ );
+ #[cfg(feature = "dim2")]
+ assert_eq!(
+ rotations.len(),
+ num_shapes,
+ "The compound rotations array must contain one angle per shape."
+ );
+ #[cfg(feature = "dim3")]
+ assert_eq!(
+ rotations.len(),
+ num_shapes * 4,
+ "The compound rotations array must contain one quaternion (4 entries) per shape."
+ );
+
+ for i in 0..num_shapes {
+ let pos_offset = i * DIM;
+
+ #[cfg(feature = "dim2")]
+ let translation = Vector::new(positions[pos_offset], positions[pos_offset + 1]);
+
+ #[cfg(feature = "dim3")]
+ let translation = Vector::new(
+ positions[pos_offset],
+ positions[pos_offset + 1],
+ positions[pos_offset + 2],
+ );
+
+ #[cfg(feature = "dim2")]
+ let rotation = Rotation::new(rotations[i]);
+
+ #[cfg(feature = "dim3")]
+ let rotation = {
+ let rot_offset = i * 4;
+ Rotation::from_xyzw(
+ rotations[rot_offset], // x
+ rotations[rot_offset + 1], // y
+ rotations[rot_offset + 2], // z
+ rotations[rot_offset + 3], // w
+ )
+ };
+
+ let pose = Pose::from_parts(translation, rotation);
+ compound_parts.push((pose, shapes[i].0.clone()));
+ }
+
+ Self(SharedShape::compound(compound_parts))
+ }
+
+ pub fn convexDecomposition(vertices: Vec, indices: Vec) -> Option {
+ Self::convexDecompositionWithParams(vertices, indices, &RawVHACDParameters::new())
+ }
+
+ pub fn convexDecompositionWithParams(
+ vertices: Vec,
+ indices: Vec,
+ params: &RawVHACDParameters,
+ ) -> Option {
+ let vertices: Vec<_> = vertices.chunks(DIM).map(|v| Vector::from_slice(v)).collect();
+ #[cfg(feature = "dim2")]
+ let indices: Vec<_> = indices.chunks(2).map(|v| [v[0], v[1]]).collect();
+ #[cfg(feature = "dim3")]
+ let indices: Vec<_> = indices.chunks(3).map(|v| [v[0], v[1], v[2]]).collect();
+
+ // Same as `SharedShape::convex_decomposition_with_params`, except that a
+ // decomposition yielding no convex part returns `None` instead of panicking
+ // when building the empty compound.
+ let decomp = VHACD::decompose(¶ms.0, &vertices, &indices, true);
+ let mut parts = vec![];
+
+ #[cfg(feature = "dim2")]
+ for hull_vertices in decomp.compute_exact_convex_hulls(&vertices, &indices) {
+ if let Some(convex) = SharedShape::convex_polyline(hull_vertices) {
+ parts.push((Pose::identity(), convex));
+ }
+ }
+
+ #[cfg(feature = "dim3")]
+ for (hull_vertices, hull_indices) in decomp.compute_exact_convex_hulls(&vertices, &indices)
+ {
+ if let Some(convex) = SharedShape::convex_mesh(hull_vertices, &hull_indices) {
+ parts.push((Pose::identity(), convex));
+ }
+ }
+
+ if parts.is_empty() {
+ return None;
+ }
+
+ Some(Self(SharedShape::compound(parts)))
+ }
+
+ pub fn castShape(
+ &self,
+ shapePos1: &RawVector,
+ shapeRot1: &RawRotation,
+ shapeVel1: &RawVector,
+ shape2: &RawShape,
+ shapePos2: &RawVector,
+ shapeRot2: &RawRotation,
+ shapeVel2: &RawVector,
+ target_distance: f32,
+ maxToi: f32,
+ stop_at_penetration: bool,
+ ) -> Option {
+ let pos1 = Pose::from_parts(shapePos1.0.into(), shapeRot1.0);
+ let pos2 = Pose::from_parts(shapePos2.0.into(), shapeRot2.0);
+
+ self.0.castShape(
+ &pos1,
+ &shapeVel1.0,
+ &*shape2.0,
+ &pos2,
+ &shapeVel2.0,
+ target_distance,
+ maxToi,
+ stop_at_penetration,
+ )
+ }
+
+ pub fn intersectsShape(
+ &self,
+ shapePos1: &RawVector,
+ shapeRot1: &RawRotation,
+ shape2: &RawShape,
+ shapePos2: &RawVector,
+ shapeRot2: &RawRotation,
+ ) -> bool {
+ let pos1 = Pose::from_parts(shapePos1.0.into(), shapeRot1.0);
+ let pos2 = Pose::from_parts(shapePos2.0.into(), shapeRot2.0);
+
+ self.0.intersectsShape(&pos1, &*shape2.0, &pos2)
+ }
+
+ pub fn contactShape(
+ &self,
+ shapePos1: &RawVector,
+ shapeRot1: &RawRotation,
+ shape2: &RawShape,
+ shapePos2: &RawVector,
+ shapeRot2: &RawRotation,
+ prediction: f32,
+ ) -> Option {
+ let pos1 = Pose::from_parts(shapePos1.0.into(), shapeRot1.0);
+ let pos2 = Pose::from_parts(shapePos2.0.into(), shapeRot2.0);
+
+ self.0.contactShape(&pos1, &*shape2.0, &pos2, prediction)
+ }
+
+ pub fn containsPoint(
+ &self,
+ shapePos: &RawVector,
+ shapeRot: &RawRotation,
+ point: &RawVector,
+ ) -> bool {
+ let pos = Pose::from_parts(shapePos.0.into(), shapeRot.0);
+
+ self.0.containsPoint(&pos, &point.0.into())
+ }
+
+ pub fn projectPoint(
+ &self,
+ shapePos: &RawVector,
+ shapeRot: &RawRotation,
+ point: &RawVector,
+ solid: bool,
+ ) -> RawPointProjection {
+ let pos = Pose::from_parts(shapePos.0.into(), shapeRot.0);
+
+ self.0.projectPoint(&pos, &point.0.into(), solid)
+ }
+
+ pub fn intersectsRay(
+ &self,
+ shapePos: &RawVector,
+ shapeRot: &RawRotation,
+ rayOrig: &RawVector,
+ rayDir: &RawVector,
+ maxToi: f32,
+ ) -> bool {
+ let pos = Pose::from_parts(shapePos.0.into(), shapeRot.0);
+
+ self.0
+ .intersectsRay(&pos, rayOrig.0.into(), rayDir.0.into(), maxToi)
+ }
+
+ pub fn castRay(
+ &self,
+ shapePos: &RawVector,
+ shapeRot: &RawRotation,
+ rayOrig: &RawVector,
+ rayDir: &RawVector,
+ maxToi: f32,
+ solid: bool,
+ ) -> f32 {
+ let pos = Pose::from_parts(shapePos.0.into(), shapeRot.0);
+
+ self.0
+ .castRay(&pos, rayOrig.0.into(), rayDir.0.into(), maxToi, solid)
+ }
+
+ pub fn castRayAndGetNormal(
+ &self,
+ shapePos: &RawVector,
+ shapeRot: &RawRotation,
+ rayOrig: &RawVector,
+ rayDir: &RawVector,
+ maxToi: f32,
+ solid: bool,
+ ) -> Option {
+ let pos = Pose::from_parts(shapePos.0.into(), shapeRot.0);
+
+ self.0
+ .castRayAndGetNormal(&pos, rayOrig.0.into(), rayDir.0.into(), maxToi, solid)
+ }
+}
+
+#[cfg(all(test, feature = "dim3"))]
+mod tests {
+ use super::RawShape;
+
+ #[test]
+ fn convex_decomposition_of_degenerate_mesh_returns_none() {
+ // A single zero-area triangle can’t produce any convex part.
+ let vertices = vec![0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 2.0, 0.0, 0.0];
+ let indices = vec![0, 1, 2];
+ assert!(RawShape::convexDecomposition(vertices, indices).is_none());
+ }
+
+ #[test]
+ fn raw_convex_mesh_accessors_round_trip_with_collinear_boundary_vertex() {
+ let vertices = vec![
+ 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0,
+ 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.5,
+ ];
+ let indices = vec![
+ [0, 2, 1],
+ [0, 3, 2],
+ [4, 5, 6],
+ [4, 6, 7],
+ [0, 1, 5],
+ [0, 5, 8],
+ [8, 5, 4],
+ [0, 8, 7],
+ [8, 4, 7],
+ [0, 7, 3],
+ [1, 2, 6],
+ [1, 6, 5],
+ [2, 3, 7],
+ [2, 7, 6],
+ ];
+ let flat_indices: Vec = indices
+ .iter()
+ .flat_map(|triangle| triangle.iter())
+ .copied()
+ .collect();
+
+ let raw_shape = RawShape::convexMesh(vertices, flat_indices).unwrap();
+ let roundtrip_vertices = raw_shape.vertices().unwrap();
+ let roundtrip_indices = raw_shape.indices().unwrap();
+
+ assert!(RawShape::convexMesh(roundtrip_vertices, roundtrip_indices).is_some());
+ }
+
+ #[test]
+ fn captured_invalid_convex_mesh_export_is_not_reconstructable() {
+ let vertices = vec![
+ -3.2503600120544434,
+ 19.476539611816406,
+ -2.0955400466918945,
+ -3.3597400188446045,
+ 19.960920333862305,
+ -2.0330400466918945,
+ -3.1253600120544434,
+ 20.30466079711914,
+ -2.126800060272217,
+ -2.3614742755889893,
+ 20.145801544189453,
+ -1.71620512008667,
+ -3.3284800052642822,
+ 20.007780075073242,
+ -1.8768000602722168,
+ -2.3614742755889893,
+ 20.138565063476562,
+ -1.8094041347503662,
+ -3.1878600120544434,
+ 19.476539611816406,
+ -1.8924200534820557,
+ -2.3614742755889893,
+ 20.05278968811035,
+ -1.4539750814437866,
+ -2.3614742755889893,
+ 20.1295166015625,
+ -1.4817370176315308,
+ -3.0941200256347656,
+ 20.382780075073242,
+ -1.8768000602722168,
+ -2.3614742755889893,
+ 19.238826751708984,
+ -1.366246223449707,
+ -2.3614742755889893,
+ 19.214706420898438,
+ -1.3726158142089844,
+ -2.3614742755889893,
+ 19.113746643066406,
+ -1.4277477264404297,
+ -2.3614742755889893,
+ 19.131973266601562,
+ -1.6892800331115723,
+ -2.3614742755889893,
+ 19.141845703125,
+ -1.792968511581421,
+ -2.526392936706543,
+ 20.19354248046875,
+ -1.9115056991577148,
+ -2.448280096054077,
+ 19.144739151000977,
+ -1.7378942966461182,
+ -2.448280096054077,
+ 19.153003692626953,
+ -1.824700117111206,
+ -2.7034800052642822,
+ 19.195280075073242,
+ -2.0174200534820557,
+ -2.448280096054077,
+ 19.155406951904297,
+ -1.8499374389648438,
+ -2.406599998474121,
+ 20.17966079711914,
+ -1.5018000602722168,
+ -2.4691200256347656,
+ 20.085920333862305,
+ -1.4705400466918945,
+ -2.688455820083618,
+ 19.69875144958496,
+ -2.0099079608917236,
+ -2.6722400188446045,
+ 20.24216079711914,
+ -2.001800060272217,
+ -2.7034800052642822,
+ 19.185195922851562,
+ -1.9115058183670044,
+ -2.6722400188446045,
+ 20.320280075073242,
+ -1.6580400466918945,
+ -2.7034800052642822,
+ 19.164039611816406,
+ -1.6892800331115723,
+ ];
+ let indices = vec![
+ 1, 4, 9, 1, 0, 4, 6, 4, 0, 6, 10, 4, 2, 1, 9, 2, 0, 1, 26, 6, 0, 26, 12, 6, 11, 6, 12,
+ 11, 10, 6, 21, 20, 25, 21, 25, 9, 21, 9, 4, 21, 4, 10, 8, 20, 21, 8, 21, 7, 26, 0, 18,
+ 13, 12, 26, 13, 26, 18, 13, 18, 14, 3, 5, 25, 3, 25, 20, 3, 20, 8, 7, 21, 10, 7, 10,
+ 11, 7, 11, 12, 7, 12, 13, 7, 13, 14, 7, 14, 5, 7, 5, 3, 7, 3, 8, 18, 0, 2, 18, 23, 5,
+ 25, 5, 23, 23, 15, 5, 23, 22, 18, 23, 18, 2, 23, 2, 9, 23, 9, 25, 18, 5, 14,
+ ];
+
+ assert!(RawShape::convexMesh(vertices, indices).is_none());
+ }
+
+ #[test]
+ fn raw_convex_hull_accessors_round_trip_with_redundant_points() {
+ let vertices = vec![
+ -3.2503600120544434,
+ 19.476539611816406,
+ -2.0955400466918945,
+ -3.3597400188446045,
+ 19.960920333862305,
+ -2.0330400466918945,
+ -3.1253600120544434,
+ 20.30466079711914,
+ -2.126800060272217,
+ -2.3614742755889893,
+ 20.145801544189453,
+ -1.71620512008667,
+ -3.3284800052642822,
+ 20.007780075073242,
+ -1.8768000602722168,
+ -2.3614742755889893,
+ 20.138565063476562,
+ -1.8094041347503662,
+ -3.1878600120544434,
+ 19.476539611816406,
+ -1.8924200534820557,
+ -2.3614742755889893,
+ 20.05278968811035,
+ -1.4539750814437866,
+ -2.3614742755889893,
+ 20.1295166015625,
+ -1.4817370176315308,
+ -3.0941200256347656,
+ 20.382780075073242,
+ -1.8768000602722168,
+ -2.3614742755889893,
+ 19.238826751708984,
+ -1.366246223449707,
+ -2.3614742755889893,
+ 19.214706420898438,
+ -1.3726158142089844,
+ -2.3614742755889893,
+ 19.113746643066406,
+ -1.4277477264404297,
+ -2.3614742755889893,
+ 19.131973266601562,
+ -1.6892800331115723,
+ -2.3614742755889893,
+ 19.141845703125,
+ -1.792968511581421,
+ -2.526392936706543,
+ 20.19354248046875,
+ -1.9115056991577148,
+ -2.448280096054077,
+ 19.144739151000977,
+ -1.7378942966461182,
+ -2.448280096054077,
+ 19.153003692626953,
+ -1.824700117111206,
+ -2.7034800052642822,
+ 19.195280075073242,
+ -2.0174200534820557,
+ -2.448280096054077,
+ 19.155406951904297,
+ -1.8499374389648438,
+ -2.406599998474121,
+ 20.17966079711914,
+ -1.5018000602722168,
+ -2.4691200256347656,
+ 20.085920333862305,
+ -1.4705400466918945,
+ -2.688455820083618,
+ 19.69875144958496,
+ -2.0099079608917236,
+ -2.6722400188446045,
+ 20.24216079711914,
+ -2.001800060272217,
+ -2.7034800052642822,
+ 19.185195922851562,
+ -1.9115058183670044,
+ -2.6722400188446045,
+ 20.320280075073242,
+ -1.6580400466918945,
+ -2.7034800052642822,
+ 19.164039611816406,
+ -1.6892800331115723,
+ ];
+
+ let raw_shape = RawShape::convexHull(vertices).unwrap();
+ let roundtrip_vertices = raw_shape.vertices().unwrap();
+ let roundtrip_indices = raw_shape.indices().unwrap();
+
+ assert!(RawShape::convexMesh(roundtrip_vertices, roundtrip_indices).is_some());
+ }
+}
diff --git a/typescript/src/geometry/toi.rs b/typescript/src/geometry/toi.rs
new file mode 100644
index 000000000..4ee1ac5a5
--- /dev/null
+++ b/typescript/src/geometry/toi.rs
@@ -0,0 +1,97 @@
+use crate::utils::{self, FlatHandle};
+use rapier::geometry::{ColliderHandle, ShapeCastHit};
+use wasm_bindgen::prelude::*;
+
+#[wasm_bindgen]
+pub struct RawShapeCastHit {
+ pub(crate) hit: ShapeCastHit,
+}
+
+#[wasm_bindgen]
+impl RawShapeCastHit {
+ #[cfg(feature = "dim2")]
+ pub fn getComponents(&self, scratch_buffer: &js_sys::Float32Array) {
+ scratch_buffer.set_index(0, self.hit.time_of_impact);
+ let mut u = self.hit.witness1;
+ scratch_buffer.set_index(1, u.x);
+ scratch_buffer.set_index(2, u.y);
+ u = self.hit.witness2;
+ scratch_buffer.set_index(3, u.x);
+ scratch_buffer.set_index(4, u.y);
+ u = self.hit.normal1;
+ scratch_buffer.set_index(5, u.x);
+ scratch_buffer.set_index(6, u.y);
+ u = self.hit.normal2;
+ scratch_buffer.set_index(7, u.x);
+ scratch_buffer.set_index(8, u.y);
+ }
+ #[cfg(feature = "dim3")]
+ pub fn getComponents(&self, scratch_buffer: &js_sys::Float32Array) {
+ scratch_buffer.set_index(0, self.hit.time_of_impact);
+ let mut u = self.hit.witness1;
+ scratch_buffer.set_index(1, u.x);
+ scratch_buffer.set_index(2, u.y);
+ scratch_buffer.set_index(3, u.z);
+ u = self.hit.witness2;
+ scratch_buffer.set_index(4, u.x);
+ scratch_buffer.set_index(5, u.y);
+ scratch_buffer.set_index(6, u.z);
+ u = self.hit.normal1;
+ scratch_buffer.set_index(7, u.x);
+ scratch_buffer.set_index(8, u.y);
+ scratch_buffer.set_index(9, u.z);
+ u = self.hit.normal2;
+ scratch_buffer.set_index(10, u.x);
+ scratch_buffer.set_index(11, u.y);
+ scratch_buffer.set_index(12, u.z);
+ }
+}
+
+#[wasm_bindgen]
+pub struct RawColliderShapeCastHit {
+ pub(crate) handle: ColliderHandle,
+ pub(crate) hit: ShapeCastHit,
+}
+
+#[wasm_bindgen]
+impl RawColliderShapeCastHit {
+ pub fn colliderHandle(&self) -> FlatHandle {
+ utils::flat_handle(self.handle.0)
+ }
+ #[cfg(feature = "dim2")]
+ pub fn getComponents(&self, scratch_buffer: &js_sys::Float32Array) {
+ scratch_buffer.set_index(0, self.hit.time_of_impact);
+ let mut u = self.hit.witness1;
+ scratch_buffer.set_index(1, u.x);
+ scratch_buffer.set_index(2, u.y);
+ u = self.hit.witness2;
+ scratch_buffer.set_index(3, u.x);
+ scratch_buffer.set_index(4, u.y);
+ u = self.hit.normal1;
+ scratch_buffer.set_index(5, u.x);
+ scratch_buffer.set_index(6, u.y);
+ u = self.hit.normal2;
+ scratch_buffer.set_index(7, u.x);
+ scratch_buffer.set_index(8, u.y);
+ }
+ #[cfg(feature = "dim3")]
+ pub fn getComponents(&self, scratch_buffer: &js_sys::Float32Array) {
+ scratch_buffer.set_index(0, self.hit.time_of_impact);
+ let mut u = self.hit.witness1;
+ scratch_buffer.set_index(1, u.x);
+ scratch_buffer.set_index(2, u.y);
+ scratch_buffer.set_index(3, u.z);
+ u = self.hit.witness2;
+ scratch_buffer.set_index(4, u.x);
+ scratch_buffer.set_index(5, u.y);
+ scratch_buffer.set_index(6, u.z);
+ u = self.hit.normal1;
+ scratch_buffer.set_index(7, u.x);
+ scratch_buffer.set_index(8, u.y);
+ scratch_buffer.set_index(9, u.z);
+ u = self.hit.normal2;
+ scratch_buffer.set_index(10, u.x);
+ scratch_buffer.set_index(11, u.y);
+ scratch_buffer.set_index(12, u.z);
+ }
+}
diff --git a/typescript/src/lib.rs b/typescript/src/lib.rs
new file mode 100644
index 000000000..132809dc6
--- /dev/null
+++ b/typescript/src/lib.rs
@@ -0,0 +1,32 @@
+//! # Rapier
+//! Fast and deterministic WASM physics engine.
+
+#![allow(non_snake_case)] // JS uses camelCase, so we will follow its convention for the generated bindings.
+ // #![deny(missing_docs)]
+
+extern crate nalgebra as na;
+#[cfg(feature = "dim2")]
+extern crate rapier2d as rapier;
+#[cfg(feature = "dim3")]
+extern crate rapier3d as rapier;
+#[macro_use]
+extern crate serde;
+
+#[wasm_bindgen::prelude::wasm_bindgen]
+pub fn version() -> String {
+ env!("CARGO_PKG_VERSION").to_string()
+}
+
+#[wasm_bindgen::prelude::wasm_bindgen]
+pub fn reserve_memory(extra_bytes_count: u32) {
+ let mut unused: Vec = vec![];
+ unused.reserve(extra_bytes_count as usize);
+ std::hint::black_box(&unused);
+}
+
+pub mod control;
+pub mod dynamics;
+pub mod geometry;
+pub mod math;
+pub mod pipeline;
+pub mod utils;
diff --git a/typescript/src/math.rs b/typescript/src/math.rs
new file mode 100644
index 000000000..2581e4af9
--- /dev/null
+++ b/typescript/src/math.rs
@@ -0,0 +1,251 @@
+//! Linear algebra primitives.
+
+#[cfg(feature = "dim3")]
+use js_sys::Float32Array;
+#[cfg(feature = "dim3")]
+use rapier::math::Real;
+use rapier::math::{Rotation, Vector};
+#[cfg(feature = "dim3")]
+use rapier::parry::utils::SdpMatrix3;
+use wasm_bindgen::prelude::*;
+
+#[wasm_bindgen]
+#[repr(transparent)]
+#[derive(Copy, Clone)]
+/// A rotation quaternion.
+pub struct RawRotation(pub(crate) Rotation);
+
+impl From for RawRotation {
+ fn from(v: Rotation) -> Self {
+ RawRotation(v)
+ }
+}
+
+#[wasm_bindgen]
+#[cfg(feature = "dim2")]
+/// A unit complex number describing the orientation of a Rapier entity.
+impl RawRotation {
+ /// The identity rotation.
+ pub fn identity() -> Self {
+ Self(Rotation::identity())
+ }
+
+ /// The rotation with thegiven angle.
+ pub fn fromAngle(angle: f32) -> Self {
+ Self(Rotation::new(angle))
+ }
+
+ /// The imaginary part of this complex number.
+ #[wasm_bindgen(getter)]
+ pub fn im(&self) -> f32 {
+ self.0.im
+ }
+
+ /// The real part of this complex number.
+ #[wasm_bindgen(getter)]
+ pub fn re(&self) -> f32 {
+ self.0.re
+ }
+
+ /// The rotation angle in radians.
+ #[wasm_bindgen(getter)]
+ pub fn angle(&self) -> f32 {
+ self.0.angle()
+ }
+}
+
+#[wasm_bindgen]
+#[cfg(feature = "dim3")]
+/// A unit quaternion describing the orientation of a Rapier entity.
+impl RawRotation {
+ #[wasm_bindgen(constructor)]
+ pub fn new(x: f32, y: f32, z: f32, w: f32) -> Self {
+ RawRotation(Rotation::from_xyzw(x, y, z, w))
+ }
+
+ /// The identity quaternion.
+ pub fn identity() -> Self {
+ Self(Rotation::IDENTITY)
+ }
+
+ /// The `x` component of this quaternion.
+ #[wasm_bindgen(getter)]
+ pub fn x(&self) -> f32 {
+ self.0.x
+ }
+
+ /// The `y` component of this quaternion.
+ #[wasm_bindgen(getter)]
+ pub fn y(&self) -> f32 {
+ self.0.y
+ }
+
+ /// The `z` component of this quaternion.
+ #[wasm_bindgen(getter)]
+ pub fn z(&self) -> f32 {
+ self.0.z
+ }
+
+ /// The `w` component of this quaternion.
+ #[wasm_bindgen(getter)]
+ pub fn w(&self) -> f32 {
+ self.0.w
+ }
+}
+
+#[wasm_bindgen]
+#[repr(transparent)]
+#[derive(Copy, Clone)]
+/// A vector.
+pub struct RawVector(pub(crate) Vector);
+
+impl From for RawVector {
+ fn from(v: Vector) -> Self {
+ RawVector(v)
+ }
+}
+
+#[wasm_bindgen]
+impl RawVector {
+ /// Creates a new vector filled with zeros.
+ pub fn zero() -> Self {
+ Self(Vector::ZERO)
+ }
+
+ /// Creates a new 2D vector from its two components.
+ ///
+ /// # Parameters
+ /// - `x`: the `x` component of this 2D vector.
+ /// - `y`: the `y` component of this 2D vector.
+ #[cfg(feature = "dim2")]
+ #[wasm_bindgen(constructor)]
+ pub fn new(x: f32, y: f32) -> Self {
+ Self(Vector::new(x, y))
+ }
+
+ /// Creates a new 3D vector from its two components.
+ ///
+ /// # Parameters
+ /// - `x`: the `x` component of this 3D vector.
+ /// - `y`: the `y` component of this 3D vector.
+ /// - `z`: the `z` component of this 3D vector.
+ #[cfg(feature = "dim3")]
+ #[wasm_bindgen(constructor)]
+ pub fn new(x: f32, y: f32, z: f32) -> Self {
+ Self(Vector::new(x, y, z))
+ }
+
+ /// The `x` component of this vector.
+ #[wasm_bindgen(getter)]
+ pub fn x(&self) -> f32 {
+ self.0.x
+ }
+
+ /// Sets the `x` component of this vector.
+ #[wasm_bindgen(setter)]
+ pub fn set_x(&mut self, x: f32) {
+ self.0.x = x
+ }
+
+ /// The `y` component of this vector.
+ #[wasm_bindgen(getter)]
+ pub fn y(&self) -> f32 {
+ self.0.y
+ }
+
+ /// Sets the `y` component of this vector.
+ #[wasm_bindgen(setter)]
+ pub fn set_y(&mut self, y: f32) {
+ self.0.y = y
+ }
+
+ /// The `z` component of this vector.
+ #[cfg(feature = "dim3")]
+ #[wasm_bindgen(getter)]
+ pub fn z(&self) -> f32 {
+ self.0.z
+ }
+
+ /// Sets the `z` component of this vector.
+ #[cfg(feature = "dim3")]
+ #[wasm_bindgen(setter)]
+ pub fn set_z(&mut self, z: f32) {
+ self.0.z = z
+ }
+
+ /// Create a new 2D vector from this vector with its components rearranged as `{x, y}`.
+ #[cfg(feature = "dim2")]
+ pub fn xy(&self) -> Self {
+ Self(Vector::new(self.0.x, self.0.y))
+ }
+
+ /// Create a new 2D vector from this vector with its components rearranged as `{y, x}`.
+ #[cfg(feature = "dim2")]
+ pub fn yx(&self) -> Self {
+ Self(Vector::new(self.0.y, self.0.x))
+ }
+
+ /// Create a new 3D vector from this vector with its components rearranged as `{x, y, z}`.
+ ///
+ /// This will effectively return a copy of `this`. This method exist for completeness with the
+ /// other swizzling functions.
+ #[cfg(feature = "dim3")]
+ pub fn xyz(&self) -> Self {
+ Self(Vector::new(self.0.x, self.0.y, self.0.z))
+ }
+
+ /// Create a new 3D vector from this vector with its components rearranged as `{y, x, z}`.
+ #[cfg(feature = "dim3")]
+ pub fn yxz(&self) -> Self {
+ Self(Vector::new(self.0.y, self.0.x, self.0.z))
+ }
+
+ /// Create a new 3D vector from this vector with its components rearranged as `{z, x, y}`.
+ #[cfg(feature = "dim3")]
+ pub fn zxy(&self) -> Self {
+ Self(Vector::new(self.0.z, self.0.x, self.0.y))
+ }
+
+ /// Create a new 3D vector from this vector with its components rearranged as `{x, z, y}`.
+ #[cfg(feature = "dim3")]
+ pub fn xzy(&self) -> Self {
+ Self(Vector::new(self.0.x, self.0.z, self.0.y))
+ }
+
+ /// Create a new 3D vector from this vector with its components rearranged as `{y, z, x}`.
+ #[cfg(feature = "dim3")]
+ pub fn yzx(&self) -> Self {
+ Self(Vector::new(self.0.y, self.0.z, self.0.x))
+ }
+
+ /// Create a new 3D vector from this vector with its components rearranged as `{z, y, x}`.
+ #[cfg(feature = "dim3")]
+ pub fn zyx(&self) -> Self {
+ Self(Vector::new(self.0.z, self.0.y, self.0.x))
+ }
+}
+
+#[wasm_bindgen]
+#[repr(transparent)]
+#[derive(Copy, Clone)]
+#[cfg(feature = "dim3")]
+pub struct RawSdpMatrix3(pub(crate) SdpMatrix3);
+
+#[cfg(feature = "dim3")]
+impl From> for RawSdpMatrix3 {
+ fn from(v: SdpMatrix3) -> Self {
+ RawSdpMatrix3(v)
+ }
+}
+
+#[wasm_bindgen]
+#[cfg(feature = "dim3")]
+impl RawSdpMatrix3 {
+ /// Row major list of the upper-triangular part of the symmetric matrix.
+ pub fn elements(&self) -> Float32Array {
+ let m = self.0;
+ let output = Float32Array::new_with_length(6);
+ output.copy_from(&[m.m11, m.m12, m.m13, m.m22, m.m23, m.m33]);
+ output
+ }
+}
diff --git a/typescript/src/pipeline/debug_render_pipeline.rs b/typescript/src/pipeline/debug_render_pipeline.rs
new file mode 100644
index 000000000..f39fff106
--- /dev/null
+++ b/typescript/src/pipeline/debug_render_pipeline.rs
@@ -0,0 +1,152 @@
+use crate::dynamics::{RawImpulseJointSet, RawMultibodyJointSet, RawRigidBodySet};
+use crate::geometry::{RawColliderSet, RawNarrowPhase};
+use js_sys::Float32Array;
+use palette::convert::IntoColorUnclamped;
+use palette::rgb::Rgba;
+use palette::Hsla;
+use rapier::dynamics::{RigidBody, RigidBodySet};
+use rapier::geometry::ColliderSet;
+use rapier::math::Vector;
+use rapier::pipeline::{DebugRenderBackend, DebugRenderObject, DebugRenderPipeline};
+use rapier::prelude::{QueryFilter, QueryFilterFlags};
+use wasm_bindgen::prelude::*;
+
+#[wasm_bindgen]
+pub struct RawDebugRenderPipeline {
+ pub(crate) raw: DebugRenderPipeline,
+ vertices: Vec,
+ colors: Vec,
+}
+
+#[wasm_bindgen]
+impl RawDebugRenderPipeline {
+ #[wasm_bindgen(constructor)]
+ pub fn new() -> Self {
+ RawDebugRenderPipeline {
+ raw: DebugRenderPipeline::default(),
+ vertices: vec![],
+ colors: vec![],
+ }
+ }
+
+ pub fn vertices(&self) -> Float32Array {
+ let output = Float32Array::new_with_length(self.vertices.len() as u32);
+ output.copy_from(&self.vertices);
+ output
+ }
+
+ pub fn colors(&self) -> Float32Array {
+ let output = Float32Array::new_with_length(self.colors.len() as u32);
+ output.copy_from(&self.colors);
+ output
+ }
+
+ pub fn render(
+ &mut self,
+ bodies: &RawRigidBodySet,
+ colliders: &RawColliderSet,
+ impulse_joints: &RawImpulseJointSet,
+ multibody_joints: &RawMultibodyJointSet,
+ narrow_phase: &RawNarrowPhase,
+ filter_flags: u32,
+ filter_predicate: &js_sys::Function,
+ ) {
+ self.vertices.clear();
+ self.colors.clear();
+
+ crate::utils::with_filter(filter_predicate, |predicate| {
+ let mut backend = CopyToBuffersBackend {
+ filter: QueryFilter {
+ flags: QueryFilterFlags::from_bits(filter_flags)
+ .unwrap_or(QueryFilterFlags::empty()),
+ groups: None,
+ exclude_collider: None,
+ exclude_rigid_body: None,
+ predicate,
+ },
+ bodies: &bodies.0,
+ colliders: &colliders.0,
+ vertices: &mut self.vertices,
+ colors: &mut self.colors,
+ };
+
+ self.raw.render(
+ &mut backend,
+ &bodies.0,
+ &colliders.0,
+ &impulse_joints.0,
+ &multibody_joints.0,
+ &narrow_phase.0,
+ )
+ })
+ }
+}
+
+struct CopyToBuffersBackend<'a> {
+ filter: QueryFilter<'a>,
+ bodies: &'a RigidBodySet,
+ colliders: &'a ColliderSet,
+ vertices: &'a mut Vec,
+ colors: &'a mut Vec,
+}
+
+impl<'a> DebugRenderBackend for CopyToBuffersBackend<'a> {
+ fn filter_object(&self, object: DebugRenderObject) -> bool {
+ let test_rigid_body = |rb: &RigidBody| {
+ rb.colliders().iter().all(|handle| {
+ let Some(co) = self.colliders.get(*handle) else {
+ return false;
+ };
+ self.filter.test(self.bodies, *handle, co)
+ })
+ };
+
+ match object {
+ DebugRenderObject::Collider(handle, co)
+ | DebugRenderObject::ColliderAabb(handle, co, _) => {
+ self.filter.test(self.bodies, handle, co)
+ }
+ DebugRenderObject::ContactPair(pair, co1, co2) => {
+ self.filter.test(self.bodies, pair.collider1, co1)
+ && self.filter.test(self.bodies, pair.collider2, co2)
+ }
+ DebugRenderObject::ImpulseJoint(_, joint) => {
+ let Some(rb1) = self.bodies.get(joint.body1()) else {
+ return false;
+ };
+ let Some(rb2) = self.bodies.get(joint.body2()) else {
+ return false;
+ };
+ test_rigid_body(rb1) && test_rigid_body(rb2)
+ }
+ DebugRenderObject::MultibodyJoint(_, _, link) => {
+ let Some(rb) = self.bodies.get(link.rigid_body_handle()) else {
+ return false;
+ };
+ test_rigid_body(rb)
+ }
+ DebugRenderObject::RigidBody(_, rb) => test_rigid_body(rb),
+ }
+ }
+
+ /// Draws a colored line.
+ ///
+ /// Note that this method can be called multiple time for the same `object`.
+ fn draw_line(
+ &mut self,
+ _object: DebugRenderObject,
+ a: Vector,
+ b: Vector,
+ color: [f32; 4],
+ ) {
+ self.vertices.extend_from_slice(&a.to_array());
+ self.vertices.extend_from_slice(&b.to_array());
+
+ // Convert to RGB which will be easier to handle in JS.
+ let hsl = Hsla::new(color[0], color[1], color[2], color[3]);
+ let rgb: Rgba = hsl.into_color_unclamped();
+ self.colors.extend_from_slice(&[
+ rgb.red, rgb.green, rgb.blue, rgb.alpha, rgb.red, rgb.green, rgb.blue, rgb.alpha,
+ ]);
+ }
+}
diff --git a/typescript/src/pipeline/event_queue.rs b/typescript/src/pipeline/event_queue.rs
new file mode 100644
index 000000000..af61b6273
--- /dev/null
+++ b/typescript/src/pipeline/event_queue.rs
@@ -0,0 +1,147 @@
+use crate::utils;
+use crate::utils::FlatHandle;
+use rapier::geometry::{CollisionEvent, ContactForceEvent};
+use rapier::pipeline::ChannelEventCollector;
+use std::sync::mpsc::Receiver;
+use wasm_bindgen::prelude::*;
+
+/// A structure responsible for collecting events generated
+/// by the physics engine.
+#[wasm_bindgen]
+pub struct RawEventQueue {
+ pub(crate) collector: ChannelEventCollector,
+ collision_events: Receiver,
+ contact_force_events: Receiver,
+ pub(crate) auto_drain: bool,
+}
+
+#[wasm_bindgen]
+pub struct RawContactForceEvent(ContactForceEvent);
+
+#[wasm_bindgen]
+impl RawContactForceEvent {
+ /// The first collider involved in the contact.
+ pub fn collider1(&self) -> FlatHandle {
+ crate::utils::flat_handle(self.0.collider1.0)
+ }
+
+ /// The second collider involved in the contact.
+ pub fn collider2(&self) -> FlatHandle {
+ crate::utils::flat_handle(self.0.collider2.0)
+ }
+
+ /// The sum of all the forces between the two colliders.
+ pub fn total_force(&self, scratch_buffer: &js_sys::Float32Array) {
+ let u = self.0.total_force;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ #[cfg(feature = "dim3")]
+ scratch_buffer.set_index(2, u.z);
+ }
+
+ /// The sum of the magnitudes of each force between the two colliders.
+ ///
+ /// Note that this is **not** the same as the magnitude of `self.total_force`.
+ /// Here we are summing the magnitude of all the forces, instead of taking
+ /// the magnitude of their sum.
+ pub fn total_force_magnitude(&self) -> f32 {
+ self.0.total_force_magnitude
+ }
+
+ /// The world-space (unit) direction of the force with strongest magnitude.
+ pub fn max_force_direction(&self, scratch_buffer: &js_sys::Float32Array) {
+ let u = self.0.max_force_direction;
+ scratch_buffer.set_index(0, u.x);
+ scratch_buffer.set_index(1, u.y);
+ #[cfg(feature = "dim3")]
+ scratch_buffer.set_index(2, u.z);
+ }
+
+ /// The magnitude of the largest force at a contact point of this contact pair.
+ pub fn max_force_magnitude(&self) -> f32 {
+ self.0.max_force_magnitude
+ }
+}
+
+// #[wasm_bindgen]
+// /// The proximity state of a sensor collider and another collider.
+// pub enum RawIntersection {
+// /// The sensor is intersecting the other collider.
+// Intersecting = 0,
+// /// The sensor is within tolerance margin of the other collider.
+// WithinMargin = 1,
+// /// The sensor is disjoint from the other collider.
+// Disjoint = 2,
+// }
+
+#[wasm_bindgen]
+impl RawEventQueue {
+ /// Creates a new event collector.
+ ///
+ /// # Parameters
+ /// - `autoDrain`: setting this to `true` is strongly recommended. If true, the collector will
+ /// be automatically drained before each `world.step(collector)`. If false, the collector will
+ /// keep all events in memory unless it is manually drained/cleared; this may lead to unbounded use of
+ /// RAM if no drain is performed.
+ #[wasm_bindgen(constructor)]
+ pub fn new(autoDrain: bool) -> Self {
+ let collision_channel = std::sync::mpsc::channel();
+ let contact_force_channel = std::sync::mpsc::channel();
+ let collector = ChannelEventCollector::new(collision_channel.0, contact_force_channel.0);
+
+ Self {
+ collector,
+ collision_events: collision_channel.1,
+ contact_force_events: contact_force_channel.1,
+ auto_drain: autoDrain,
+ }
+ }
+
+ /// Applies the given javascript closure on each collision event of this collector, then clear
+ /// the internal collision event buffer.
+ ///
+ /// # Parameters
+ /// - `f(handle1, handle2, started)`: JavaScript closure applied to each collision event. The
+ /// closure should take three arguments: two integers representing the handles of the colliders
+ /// involved in the collision, and a boolean indicating if the collision started (true) or stopped
+ /// (false).
+ pub fn drainCollisionEvents(&mut self, f: &js_sys::Function) {
+ let this = JsValue::null();
+ while let Ok(event) = self.collision_events.try_recv() {
+ match event {
+ CollisionEvent::Started(co1, co2, _) => {
+ let h1 = utils::flat_handle(co1.0);
+ let h2 = utils::flat_handle(co2.0);
+ let _ = f.call3(
+ &this,
+ &JsValue::from(h1),
+ &JsValue::from(h2),
+ &JsValue::from_bool(true),
+ );
+ }
+ CollisionEvent::Stopped(co1, co2, _) => {
+ let h1 = utils::flat_handle(co1.0);
+ let h2 = utils::flat_handle(co2.0);
+ let _ = f.call3(
+ &this,
+ &JsValue::from(h1),
+ &JsValue::from(h2),
+ &JsValue::from_bool(false),
+ );
+ }
+ }
+ }
+ }
+
+ pub fn drainContactForceEvents(&mut self, f: &js_sys::Function) {
+ let this = JsValue::null();
+ while let Ok(event) = self.contact_force_events.try_recv() {
+ let _ = f.call1(&this, &JsValue::from(RawContactForceEvent(event)));
+ }
+ }
+
+ /// Removes all events contained by this collector.
+ pub fn clear(&self) {
+ while let Ok(_) = self.collision_events.try_recv() {}
+ }
+}
diff --git a/typescript/src/pipeline/mod.rs b/typescript/src/pipeline/mod.rs
new file mode 100644
index 000000000..23e19bfb0
--- /dev/null
+++ b/typescript/src/pipeline/mod.rs
@@ -0,0 +1,11 @@
+pub use self::debug_render_pipeline::*;
+pub use self::event_queue::*;
+pub use self::physics_hooks::*;
+pub use self::physics_pipeline::*;
+pub use self::serialization_pipeline::*;
+
+mod debug_render_pipeline;
+mod event_queue;
+mod physics_hooks;
+mod physics_pipeline;
+mod serialization_pipeline;
diff --git a/typescript/src/pipeline/physics_hooks.rs b/typescript/src/pipeline/physics_hooks.rs
new file mode 100644
index 000000000..2bbc80340
--- /dev/null
+++ b/typescript/src/pipeline/physics_hooks.rs
@@ -0,0 +1,217 @@
+use crate::utils;
+use rapier::geometry::SolverFlags;
+use rapier::pipeline::{ContactModificationContext, PairFilterContext, PhysicsHooks};
+use wasm_bindgen::prelude::*;
+
+pub struct RawPhysicsHooks {
+ pub this: js_sys::Object,
+ pub filter_contact_pair: js_sys::Function,
+ pub filter_intersection_pair: js_sys::Function,
+ // pub modify_solver_contacts: &'a js_sys::Function,
+}
+
+// HACK: the RawPhysicsHooks is no longer Send+Sync because the JS objects are
+// no longer Send+Sync since https://github.com/rustwasm/wasm-bindgen/pull/955
+// As far as this is confined to the bindings this should be fine since we
+// never use threading in wasm.
+unsafe impl Send for RawPhysicsHooks {}
+unsafe impl Sync for RawPhysicsHooks {}
+
+#[wasm_bindgen]
+extern "C" {
+ // Use `js_namespace` here to bind `console.log(..)` instead of just
+ // `log(..)`
+ #[wasm_bindgen(js_namespace = console)]
+ fn log(s: &str);
+}
+
+impl PhysicsHooks for RawPhysicsHooks {
+ fn filter_contact_pair(&self, ctxt: &PairFilterContext) -> Option {
+ let rb1 = ctxt
+ .rigid_body1
+ .map(|rb| JsValue::from(utils::flat_handle(rb.0)))
+ .unwrap_or(JsValue::NULL);
+ let rb2 = ctxt
+ .rigid_body2
+ .map(|rb| JsValue::from(utils::flat_handle(rb.0)))
+ .unwrap_or(JsValue::NULL);
+
+ let result = self
+ .filter_contact_pair
+ .bind2(
+ &self.this,
+ &JsValue::from(utils::flat_handle(ctxt.collider1.0)),
+ &JsValue::from(utils::flat_handle(ctxt.collider2.0)),
+ )
+ .call2(&self.this, &rb1, &rb2)
+ .ok()?;
+ let flags = result.as_f64()?;
+ // TODO: not sure exactly why we have to do `flags as u32` instead
+ // of `flags.to_bits() as u32`.
+ SolverFlags::from_bits(flags as u32)
+ }
+
+ fn filter_intersection_pair(&self, ctxt: &PairFilterContext) -> bool {
+ let rb1 = ctxt
+ .rigid_body1
+ .map(|rb| JsValue::from(utils::flat_handle(rb.0)))
+ .unwrap_or(JsValue::NULL);
+ let rb2 = ctxt
+ .rigid_body2
+ .map(|rb| JsValue::from(utils::flat_handle(rb.0)))
+ .unwrap_or(JsValue::NULL);
+
+ self.filter_intersection_pair
+ .bind2(
+ &self.this,
+ &JsValue::from(utils::flat_handle(ctxt.collider1.0)),
+ &JsValue::from(utils::flat_handle(ctxt.collider2.0)),
+ )
+ .call2(&self.this, &rb1, &rb2)
+ .ok()
+ .and_then(|res| res.as_bool())
+ .unwrap_or(false)
+ }
+
+ fn modify_solver_contacts(&self, _ctxt: &mut ContactModificationContext) {}
+}
+
+/* NOTE: the following is an attempt to make contact modification work.
+ *
+#[wasm_bindgen]
+#[derive(Copy, Clone, Debug)]
+pub struct RawContactManifold(*const ContactManifold);
+pub struct RawSolverContact(*const SolverContact);
+
+#[wasm_bindgen]
+pub struct RawContactModificationContext {
+ pub collider1: u32,
+ pub collider2: u32,
+ pub rigid_body1: Option,
+ pub rigid_body2: Option,
+ pub manifold: *const ContactManifold,
+ pub solver_contacts: *mut Vec,
+ normal: *mut Vector,
+ user_data: *mut u32,
+}
+
+#[wasm_bindgen]
+impl RawContactModificationContext {
+ pub fn collider1(&self) -> u32 {
+ self.collider1
+ }
+
+ pub fn collider2(&self) -> u32 {
+ self.collider2
+ }
+
+ #[wasm_bindgen(getter)]
+ pub fn normal(&self) -> RawVector {
+ unsafe { RawVector(*self.normal) }
+ }
+
+ #[wasm_bindgen(setter)]
+ pub fn set_normal(&mut self, normal: RawVector) {
+ unsafe {
+ *self.normal = normal.0;
+ }
+ }
+
+ #[wasm_bindgen(getter)]
+ pub fn user_data(&self) -> u32 {
+ unsafe { *self.user_data }
+ }
+
+ #[wasm_bindgen(setter)]
+ pub fn set_user_data(&mut self, user_data: u32) {
+ unsafe {
+ *self.user_data = user_data;
+ }
+ }
+
+ pub fn num_solver_contacts(&self) -> usize {
+ unsafe { (*self.solver_contacts).len() }
+ }
+
+ pub fn clear_solver_contacts(&mut self) {
+ unsafe { (*self.solver_contacts).clear() }
+ }
+
+ pub fn remove_solver_contact(&mut self, i: usize) {
+ unsafe {
+ if i < self.num_solver_contacts() {
+ (*self.solver_contacts).swap_remove(i);
+ }
+ }
+ }
+
+ pub fn solver_contact_point(&self, i: usize) -> Option {
+ unsafe {
+ (*self.solver_contacts)
+ .get(i)
+ .map(|c| c.point.coords.into())
+ }
+ }
+
+ pub fn set_solver_contact_point(&mut self, i: usize, pt: &RawVector) {
+ unsafe {
+ if let Some(c) = (*self.solver_contacts).get_mut(i) {
+ c.point = pt.0.into()
+ }
+ }
+ }
+
+ pub fn solver_contact_dist(&self, i: usize) -> Real {
+ unsafe {
+ (*self.solver_contacts)
+ .get(i)
+ .map(|c| c.dist)
+ .unwrap_or(0.0)
+ }
+ }
+
+ pub fn set_solver_contact_dist(&mut self, i: usize, dist: Real) {
+ unsafe {
+ if let Some(c) = (*self.solver_contacts).get_mut(i) {
+ c.dist = dist
+ }
+ }
+ }
+
+ pub fn solver_contact_friction(&self, i: usize) -> Real {
+ unsafe { (*self.solver_contacts)[i].friction }
+ }
+
+ pub fn set_solver_contact_friction(&mut self, i: usize, friction: Real) {
+ unsafe {
+ if let Some(c) = (*self.solver_contacts).get_mut(i) {
+ c.friction = friction
+ }
+ }
+ }
+
+ pub fn solver_contact_restitution(&self, i: usize) -> Real {
+ unsafe { (*self.solver_contacts)[i].restitution }
+ }
+
+ pub fn set_solver_contact_restitution(&mut self, i: usize, restitution: Real) {
+ unsafe {
+ if let Some(c) = (*self.solver_contacts).get_mut(i) {
+ c.restitution = restitution
+ }
+ }
+ }
+
+ pub fn solver_contact_tangent_velocity(&self, i: usize) -> RawVector {
+ unsafe { (*self.solver_contacts)[i].tangent_velocity.into() }
+ }
+
+ pub fn set_solver_contact_tangent_velocity(&mut self, i: usize, vel: &RawVector) {
+ unsafe {
+ if let Some(c) = (*self.solver_contacts).get_mut(i) {
+ c.tangent_velocity = vel.0.into()
+ }
+ }
+ }
+}
+*/
diff --git a/typescript/src/pipeline/physics_pipeline.rs b/typescript/src/pipeline/physics_pipeline.rs
new file mode 100644
index 000000000..e844ed995
--- /dev/null
+++ b/typescript/src/pipeline/physics_pipeline.rs
@@ -0,0 +1,170 @@
+use crate::dynamics::{
+ RawCCDSolver, RawImpulseJointSet, RawIntegrationParameters, RawIslandManager,
+ RawMultibodyJointSet, RawRigidBodySet,
+};
+use crate::geometry::{RawBroadPhase, RawColliderSet, RawNarrowPhase};
+use crate::math::RawVector;
+use crate::pipeline::{RawEventQueue, RawPhysicsHooks};
+use crate::rapier::pipeline::PhysicsPipeline;
+use wasm_bindgen::prelude::*;
+
+#[wasm_bindgen]
+pub struct RawPhysicsPipeline(pub(crate) PhysicsPipeline);
+
+#[wasm_bindgen]
+impl RawPhysicsPipeline {
+ #[wasm_bindgen(constructor)]
+ pub fn new() -> Self {
+ let mut pipeline = PhysicsPipeline::new();
+ pipeline.counters.disable(); // Disable perf counters by default.
+ RawPhysicsPipeline(pipeline)
+ }
+
+ pub fn set_profiler_enabled(&mut self, enabled: bool) {
+ if enabled {
+ self.0.counters.enable();
+ } else {
+ self.0.counters.disable();
+ }
+ }
+
+ pub fn is_profiler_enabled(&self) -> bool {
+ self.0.counters.enabled()
+ }
+
+ pub fn timing_step(&self) -> f64 {
+ self.0.counters.step_time_ms()
+ }
+
+ pub fn timing_collision_detection(&self) -> f64 {
+ self.0.counters.collision_detection_time_ms()
+ }
+
+ pub fn timing_broad_phase(&self) -> f64 {
+ self.0.counters.broad_phase_time_ms()
+ }
+
+ pub fn timing_narrow_phase(&self) -> f64 {
+ self.0.counters.narrow_phase_time_ms()
+ }
+
+ pub fn timing_solver(&self) -> f64 {
+ self.0.counters.solver_time_ms()
+ }
+
+ pub fn timing_velocity_assembly(&self) -> f64 {
+ self.0.counters.solver.velocity_assembly_time.time_ms()
+ }
+
+ pub fn timing_velocity_resolution(&self) -> f64 {
+ self.0.counters.velocity_resolution_time_ms()
+ }
+
+ pub fn timing_velocity_update(&self) -> f64 {
+ self.0.counters.velocity_update_time_ms()
+ }
+
+ pub fn timing_velocity_writeback(&self) -> f64 {
+ self.0.counters.solver.velocity_writeback_time.time_ms()
+ }
+
+ pub fn timing_ccd(&self) -> f64 {
+ self.0.counters.ccd_time_ms()
+ }
+
+ pub fn timing_ccd_toi_computation(&self) -> f64 {
+ self.0.counters.ccd.toi_computation_time.time_ms()
+ }
+
+ pub fn timing_ccd_broad_phase(&self) -> f64 {
+ self.0.counters.ccd.broad_phase_time.time_ms()
+ }
+
+ pub fn timing_ccd_narrow_phase(&self) -> f64 {
+ self.0.counters.ccd.narrow_phase_time.time_ms()
+ }
+
+ pub fn timing_ccd_solver(&self) -> f64 {
+ self.0.counters.ccd.solver_time.time_ms()
+ }
+
+ pub fn timing_island_construction(&self) -> f64 {
+ self.0.counters.island_construction_time_ms()
+ }
+
+ pub fn timing_user_changes(&self) -> f64 {
+ self.0.counters.stages.user_changes.time_ms()
+ }
+
+ pub fn step(
+ &mut self,
+ gravity: &RawVector,
+ integrationParameters: &RawIntegrationParameters,
+ islands: &mut RawIslandManager,
+ broadPhase: &mut RawBroadPhase,
+ narrowPhase: &mut RawNarrowPhase,
+ bodies: &mut RawRigidBodySet,
+ colliders: &mut RawColliderSet,
+ joints: &mut RawImpulseJointSet,
+ articulations: &mut RawMultibodyJointSet,
+ ccd_solver: &mut RawCCDSolver,
+ ) {
+ self.0.step(
+ gravity.0,
+ &integrationParameters.0,
+ &mut islands.0,
+ &mut broadPhase.0,
+ &mut narrowPhase.0,
+ &mut bodies.0,
+ &mut colliders.0,
+ &mut joints.0,
+ &mut articulations.0,
+ &mut ccd_solver.0,
+ &(),
+ &(),
+ );
+ }
+
+ pub fn stepWithEvents(
+ &mut self,
+ gravity: &RawVector,
+ integrationParameters: &RawIntegrationParameters,
+ islands: &mut RawIslandManager,
+ broadPhase: &mut RawBroadPhase,
+ narrowPhase: &mut RawNarrowPhase,
+ bodies: &mut RawRigidBodySet,
+ colliders: &mut RawColliderSet,
+ joints: &mut RawImpulseJointSet,
+ articulations: &mut RawMultibodyJointSet,
+ ccd_solver: &mut RawCCDSolver,
+ eventQueue: &mut RawEventQueue,
+ hookObject: js_sys::Object,
+ hookFilterContactPair: js_sys::Function,
+ hookFilterIntersectionPair: js_sys::Function,
+ ) {
+ if eventQueue.auto_drain {
+ eventQueue.clear();
+ }
+
+ let hooks = RawPhysicsHooks {
+ this: hookObject,
+ filter_contact_pair: hookFilterContactPair,
+ filter_intersection_pair: hookFilterIntersectionPair,
+ };
+
+ self.0.step(
+ gravity.0,
+ &integrationParameters.0,
+ &mut islands.0,
+ &mut broadPhase.0,
+ &mut narrowPhase.0,
+ &mut bodies.0,
+ &mut colliders.0,
+ &mut joints.0,
+ &mut articulations.0,
+ &mut ccd_solver.0,
+ &hooks,
+ &eventQueue.collector,
+ );
+ }
+}
diff --git a/typescript/src/pipeline/serialization_pipeline.rs b/typescript/src/pipeline/serialization_pipeline.rs
new file mode 100644
index 000000000..8d2e841ad
--- /dev/null
+++ b/typescript/src/pipeline/serialization_pipeline.rs
@@ -0,0 +1,145 @@
+use crate::dynamics::{
+ RawImpulseJointSet, RawIntegrationParameters, RawIslandManager, RawMultibodyJointSet,
+ RawRigidBodySet,
+};
+use crate::geometry::{RawBroadPhase, RawColliderSet, RawNarrowPhase};
+use crate::math::RawVector;
+use js_sys::Uint8Array;
+use rapier::dynamics::{
+ ImpulseJointSet, IntegrationParameters, IslandManager, MultibodyJointSet, RigidBodySet,
+};
+use rapier::geometry::{ColliderSet, DefaultBroadPhase, NarrowPhase};
+use rapier::math::Vector;
+use wasm_bindgen::prelude::*;
+
+#[derive(Serialize)]
+struct SerializableWorld<'a> {
+ gravity: &'a Vector,
+ integration_parameters: &'a IntegrationParameters,
+ islands: &'a IslandManager,
+ broad_phase: &'a DefaultBroadPhase,
+ narrow_phase: &'a NarrowPhase,
+ bodies: &'a RigidBodySet,
+ colliders: &'a ColliderSet,
+ impulse_joints: &'a ImpulseJointSet,
+ multibody_joints: &'a MultibodyJointSet,
+}
+
+#[derive(Deserialize)]
+struct DeserializableWorld {
+ gravity: Vector,
+ integration_parameters: IntegrationParameters,
+ islands: IslandManager,
+ broad_phase: DefaultBroadPhase,
+ narrow_phase: NarrowPhase,
+ bodies: RigidBodySet,
+ colliders: ColliderSet,
+ impulse_joints: ImpulseJointSet,
+ multibody_joints: MultibodyJointSet,
+}
+
+#[wasm_bindgen]
+pub struct RawDeserializedWorld {
+ gravity: Option,
+ integrationParameters: Option,
+ islands: Option,
+ broadPhase: Option,
+ narrowPhase: Option,
+ bodies: Option,
+ colliders: Option,
+ impulse_joints: Option,
+ multibody_joints: Option,
+}
+
+#[wasm_bindgen]
+impl RawDeserializedWorld {
+ pub fn takeGravity(&mut self) -> Option {
+ self.gravity.take()
+ }
+
+ pub fn takeIntegrationParameters(&mut self) -> Option {
+ self.integrationParameters.take()
+ }
+
+ pub fn takeIslandManager(&mut self) -> Option {
+ self.islands.take()
+ }
+
+ pub fn takeBroadPhase(&mut self) -> Option {
+ self.broadPhase.take()
+ }
+
+ pub fn takeNarrowPhase(&mut self) -> Option {
+ self.narrowPhase.take()
+ }
+
+ pub fn takeBodies(&mut self) -> Option {
+ self.bodies.take()
+ }
+
+ pub fn takeColliders(&mut self) -> Option {
+ self.colliders.take()
+ }
+
+ pub fn takeImpulseJoints(&mut self) -> Option {
+ self.impulse_joints.take()
+ }
+
+ pub fn takeMultibodyJoints(&mut self) -> Option {
+ self.multibody_joints.take()
+ }
+}
+
+#[wasm_bindgen]
+pub struct RawSerializationPipeline;
+
+#[wasm_bindgen]
+impl RawSerializationPipeline {
+ #[wasm_bindgen(constructor)]
+ pub fn new() -> Self {
+ RawSerializationPipeline
+ }
+
+ pub fn serializeAll(
+ &self,
+ gravity: &RawVector,
+ integrationParameters: &RawIntegrationParameters,
+ islands: &RawIslandManager,
+ broadPhase: &RawBroadPhase,
+ narrowPhase: &RawNarrowPhase,
+ bodies: &RawRigidBodySet,
+ colliders: &RawColliderSet,
+ impulse_joints: &RawImpulseJointSet,
+ multibody_joints: &RawMultibodyJointSet,
+ ) -> Option {
+ let to_serialize = SerializableWorld {
+ gravity: &gravity.0,
+ integration_parameters: &integrationParameters.0,
+ islands: &islands.0,
+ broad_phase: &broadPhase.0,
+ narrow_phase: &narrowPhase.0,
+ bodies: &bodies.0,
+ colliders: &colliders.0,
+ impulse_joints: &impulse_joints.0,
+ multibody_joints: &multibody_joints.0,
+ };
+ let snap = bincode::serialize(&to_serialize).ok()?;
+ Some(Uint8Array::from(&snap[..]))
+ }
+
+ pub fn deserializeAll(&self, data: Uint8Array) -> Option {
+ let data = data.to_vec();
+ let d: DeserializableWorld = bincode::deserialize(&data[..]).ok()?;
+ Some(RawDeserializedWorld {
+ gravity: Some(RawVector(d.gravity)),
+ integrationParameters: Some(RawIntegrationParameters(d.integration_parameters)),
+ islands: Some(RawIslandManager(d.islands)),
+ broadPhase: Some(RawBroadPhase(d.broad_phase)),
+ narrowPhase: Some(RawNarrowPhase(d.narrow_phase)),
+ bodies: Some(RawRigidBodySet(d.bodies)),
+ colliders: Some(RawColliderSet(d.colliders)),
+ impulse_joints: Some(RawImpulseJointSet(d.impulse_joints)),
+ multibody_joints: Some(RawMultibodyJointSet(d.multibody_joints)),
+ })
+ }
+}
diff --git a/typescript/src/utils.rs b/typescript/src/utils.rs
new file mode 100644
index 000000000..1b46e7cc8
--- /dev/null
+++ b/typescript/src/utils.rs
@@ -0,0 +1,79 @@
+use rapier::data::Index;
+use rapier::dynamics::{ImpulseJointHandle, MultibodyJointHandle, RigidBodyHandle};
+use rapier::geometry::{Collider, ColliderHandle};
+use wasm_bindgen::JsValue;
+
+pub type FlatHandle = f64;
+
+#[inline(always)]
+pub fn collider_handle(id: FlatHandle) -> ColliderHandle {
+ ColliderHandle::from_raw_parts(id.to_bits() as u32, (id.to_bits() >> 32) as u32)
+}
+
+#[inline(always)]
+pub fn body_handle(id: FlatHandle) -> RigidBodyHandle {
+ RigidBodyHandle::from_raw_parts(id.to_bits() as u32, (id.to_bits() >> 32) as u32)
+}
+
+#[inline(always)]
+pub fn impulse_joint_handle(id: FlatHandle) -> ImpulseJointHandle {
+ ImpulseJointHandle::from_raw_parts(id.to_bits() as u32, (id.to_bits() >> 32) as u32)
+}
+
+#[inline(always)]
+pub fn multibody_joint_handle(id: FlatHandle) -> MultibodyJointHandle {
+ MultibodyJointHandle::from_raw_parts(id.to_bits() as u32, (id.to_bits() >> 32) as u32)
+}
+
+#[inline(always)]
+pub fn flat_handle(id: Index) -> FlatHandle {
+ let (i, g) = id.into_raw_parts();
+ FlatHandle::from_bits(i as u64 | ((g as u64) << 32))
+}
+
+// pub type FlatHandle = u32;
+//
+// #[inline(always)]
+// pub fn collider_handle(id: FlatHandle) -> ColliderHandle {
+// ColliderHandle::from_raw_parts(id as u32, (id >> 16) as u32)
+// }
+//
+// #[inline(always)]
+// pub fn body_handle(id: FlatHandle) -> RigidBodyHandle {
+// RigidBodyHandle::from_raw_parts(id as u32, (id >> 16) as u32)
+// }
+//
+// #[inline(always)]
+// pub fn impulse_joint_handle(id: FlatHandle) -> ImpulseJointHandle {
+// ImpulseJointHandle::from_raw_parts(id as u32, (id >> 16) as u32)
+// }
+//
+// #[inline(always)]
+// pub fn multibody_joint_handle(id: FlatHandle) -> MultibodyJointHandle {
+// MultibodyJointHandle::from_raw_parts(id as u32, (id >> 16) as u32)
+// }
+//
+// #[inline(always)]
+// pub fn flat_handle(id: Index) -> FlatHandle {
+// let (i, g) = id.into_raw_parts();
+// i as u32 | ((g as u32) << 16)
+// }
+
+#[inline(always)]
+pub fn with_filter(
+ filter: &js_sys::Function,
+ f: impl FnOnce(Option<&dyn Fn(ColliderHandle, &Collider) -> bool>) -> T,
+) -> T {
+ if filter.is_function() {
+ let filtercb = move |handle: ColliderHandle, _: &Collider| match filter
+ .call1(&JsValue::null(), &JsValue::from(flat_handle(handle.0)))
+ {
+ Err(_) => true,
+ Ok(val) => val.as_bool().unwrap_or(true),
+ };
+
+ f(Some(&filtercb))
+ } else {
+ f(None)
+ }
+}
diff --git a/typescript/testbed2d/.npmignore b/typescript/testbed2d/.npmignore
new file mode 100644
index 000000000..488f91257
--- /dev/null
+++ b/typescript/testbed2d/.npmignore
@@ -0,0 +1,3 @@
+webpack.config2d.js
+src
+*.tgz
\ No newline at end of file
diff --git a/typescript/testbed2d/package-lock.json b/typescript/testbed2d/package-lock.json
new file mode 100644
index 000000000..4777a9ac5
--- /dev/null
+++ b/typescript/testbed2d/package-lock.json
@@ -0,0 +1,7435 @@
+{
+ "name": "rapier-testbed2d",
+ "version": "0.1.0",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "rapier-testbed2d",
+ "version": "0.1.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@dimforge/rapier2d": "file:../builds/rapier2d",
+ "hash-wasm": "^4.12.0",
+ "lil-gui": "^0.17.0",
+ "pixi-viewport": "^4.37.0",
+ "pixi.js": "^6.3.2",
+ "seedrandom": "^3.0.5",
+ "stats.js": "^0.17.0"
+ },
+ "devDependencies": {
+ "@types/seedrandom": "^3.0.2",
+ "@types/stats.js": "^0.17.0",
+ "copy-webpack-plugin": "^11.0.0",
+ "rimraf": "^3.0.2",
+ "ts-loader": "^9.4.1",
+ "typescript": "^4.8.4",
+ "webpack": "^5.74.0",
+ "webpack-cli": "^4.10.0",
+ "webpack-dev-server": "^4.11.1"
+ }
+ },
+ "../builds/rapier2d": {
+ "name": "@dimforge/rapier2d",
+ "dependencies": {
+ "wasm-pack": "^0.12.1"
+ },
+ "devDependencies": {
+ "rimraf": "^3.0.2",
+ "typedoc": "^0.25.13"
+ }
+ },
+ "../rapier2d": {
+ "name": "@dimforge/rapier2d",
+ "extraneous": true,
+ "dependencies": {
+ "wasm-pack": "^0.12.1"
+ },
+ "devDependencies": {
+ "rimraf": "^3.0.2",
+ "typedoc": "^0.25.13"
+ }
+ },
+ "node_modules/@dimforge/rapier2d": {
+ "resolved": "../builds/rapier2d",
+ "link": true
+ },
+ "node_modules/@discoveryjs/json-ext": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
+ "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz",
+ "integrity": "sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/set-array": "^1.0.0",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz",
+ "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/set-array": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.1.tgz",
+ "integrity": "sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/source-map": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz",
+ "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.0",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.4.13",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz",
+ "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==",
+ "dev": true
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.13",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz",
+ "integrity": "sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
+ "node_modules/@leichtgewicht/ip-codec": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz",
+ "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==",
+ "dev": true
+ },
+ "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,
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@pixi/accessibility": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/accessibility/-/accessibility-6.5.8.tgz",
+ "integrity": "sha512-3q1YaZeZKOoblgbxTQg2L0RAp9jtNtGcl/7kce+XelqxwIMS3p8411nwo90YO53XCqc/eQW2SoZ+hSXqcL0qOw==",
+ "peerDependencies": {
+ "@pixi/core": "6.5.8",
+ "@pixi/display": "6.5.8",
+ "@pixi/utils": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/app": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/app/-/app-6.5.8.tgz",
+ "integrity": "sha512-pDPkamtYDaPhscNxack+bHNqazCwrqw6cAotKyoz1mvLXeGhxqTntOcfgGLZR2fNbnY8EBmdduLvH7n2jI/LTg==",
+ "peerDependencies": {
+ "@pixi/core": "6.5.8",
+ "@pixi/display": "6.5.8",
+ "@pixi/math": "6.5.8",
+ "@pixi/utils": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/compressed-textures": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/compressed-textures/-/compressed-textures-6.5.8.tgz",
+ "integrity": "sha512-nW74kcvdEoe4a2U7Ekx4egqdH1tYKC2kCOZxKWYcUARqz26tS0ddwSRyIs05In6EChmXHXGy/MtShdueMH38TA==",
+ "peerDependencies": {
+ "@pixi/constants": "6.5.8",
+ "@pixi/core": "6.5.8",
+ "@pixi/loaders": "6.5.8",
+ "@pixi/settings": "6.5.8",
+ "@pixi/utils": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/constants": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/constants/-/constants-6.5.8.tgz",
+ "integrity": "sha512-yYRCebBPqajm1kn5f8QQTTvl7oDRDk1nppfO+JpqbrFXg0W7oqIMurec3KeG9RdZW5foOiXDoz1Gw+VtolYIEw=="
+ },
+ "node_modules/@pixi/core": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/core/-/core-6.5.8.tgz",
+ "integrity": "sha512-Gconik7/PpFPMpCpOddXVIPx5C2StWKw7lQ4YX19yQ+cRRmecCea2cV0xTBtpEjjx0ilX7nBfIEuZ4zIlMmlbA==",
+ "dependencies": {
+ "@types/offscreencanvas": "^2019.6.4"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/pixijs"
+ },
+ "peerDependencies": {
+ "@pixi/constants": "6.5.8",
+ "@pixi/extensions": "6.5.8",
+ "@pixi/math": "6.5.8",
+ "@pixi/runner": "6.5.8",
+ "@pixi/settings": "6.5.8",
+ "@pixi/ticker": "6.5.8",
+ "@pixi/utils": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/display": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/display/-/display-6.5.8.tgz",
+ "integrity": "sha512-2K8YOG8s0iF8x/k2Q0RTFmoMJ9biI6PXEh76nH3EqUFdpyrIIgrG5aOMnCkVDvOxlgVRrKG8Q3JBHlSievTmuw==",
+ "peerDependencies": {
+ "@pixi/constants": "6.5.8",
+ "@pixi/math": "6.5.8",
+ "@pixi/settings": "6.5.8",
+ "@pixi/utils": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/extensions": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/extensions/-/extensions-6.5.8.tgz",
+ "integrity": "sha512-6vEV801Vn/EkU/qjFiZ76OZWPq5KsBR2r+P5gfKv4YLnaDc3A+0IpUOJ7sLBAJqmr0iw68g6xV6MnuqVjNGjFg=="
+ },
+ "node_modules/@pixi/extract": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/extract/-/extract-6.5.8.tgz",
+ "integrity": "sha512-qbuuD/iBA4J+TCBgrbMe8oDUFbCriyy9LTKEtQp+pghKD5MEMvJ3nO6Osumxqiqta2kYU6WldFLTldKyHEiQ7Q==",
+ "peerDependencies": {
+ "@pixi/core": "6.5.8",
+ "@pixi/math": "6.5.8",
+ "@pixi/utils": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/filter-alpha": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/filter-alpha/-/filter-alpha-6.5.8.tgz",
+ "integrity": "sha512-W4IkFTLTP84H+DS9XIdBGunAEpaXLrasDc4CQBeyp4c4hBlGlzriUZp30vkmqm7GPmFhzPe7aiJtNYgUpxKQBQ==",
+ "peerDependencies": {
+ "@pixi/core": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/filter-blur": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/filter-blur/-/filter-blur-6.5.8.tgz",
+ "integrity": "sha512-1UOfVthFBnavzTBkR6R+1tWhOOymtWvcpuJILhxf3mryLj9eqYbQubAG0gV8Da6Ibsgk+v73ORnOJyWR3POFvw==",
+ "peerDependencies": {
+ "@pixi/constants": "6.5.8",
+ "@pixi/core": "6.5.8",
+ "@pixi/settings": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/filter-color-matrix": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/filter-color-matrix/-/filter-color-matrix-6.5.8.tgz",
+ "integrity": "sha512-iix+a/KEi6HAwZwkUH3nkIzyLu0ln3HBuHEFLUUhug7xrQgQgGrTQZ32iWlfpJD/BZuKphIGfzlxMFfvyQmkVw==",
+ "peerDependencies": {
+ "@pixi/core": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/filter-displacement": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/filter-displacement/-/filter-displacement-6.5.8.tgz",
+ "integrity": "sha512-qLRka5cQbeH6667A+ViYoemsXGGe2tOBt92vM91+slMt9OBGtR0ymlpGU7VxBggWUlu5PE10zYed/xw78uSpig==",
+ "peerDependencies": {
+ "@pixi/core": "6.5.8",
+ "@pixi/math": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/filter-fxaa": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/filter-fxaa/-/filter-fxaa-6.5.8.tgz",
+ "integrity": "sha512-TxsBH2z2RMj0mqr13VPi18/EJ/Kn38J2u65HonJmhbvTaoK9HWMExTvl38Xjg0k7TlepwhoayxMhQ1uCw9xudQ==",
+ "peerDependencies": {
+ "@pixi/core": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/filter-noise": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/filter-noise/-/filter-noise-6.5.8.tgz",
+ "integrity": "sha512-BZHKuzV5Mdn+EpC52lFYpd6jUcrL+YQHdq0v0yJfVtpW2ripseQxMGxxXr6Yxp2P4F3g2aY2JrfX2VztosmGLA==",
+ "peerDependencies": {
+ "@pixi/core": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/graphics": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/graphics/-/graphics-6.5.8.tgz",
+ "integrity": "sha512-DUuUXHO4t5fg+n+srMkHX38QEH3WtS1IMXtovBGFJkkopG0Z0xjxSp5XvsPPw1J//4fzkHZI5OBrlN613p9+sg==",
+ "peerDependencies": {
+ "@pixi/constants": "6.5.8",
+ "@pixi/core": "6.5.8",
+ "@pixi/display": "6.5.8",
+ "@pixi/math": "6.5.8",
+ "@pixi/sprite": "6.5.8",
+ "@pixi/utils": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/interaction": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/interaction/-/interaction-6.5.8.tgz",
+ "integrity": "sha512-uP247r0f47vo9WSpEnsUfeD1izxVGpjtg4iAyGT/02ezWse2vD1aEL8AbxFa65TL0IXOKsHEQudCVL+wjnbSKQ==",
+ "peerDependencies": {
+ "@pixi/core": "6.5.8",
+ "@pixi/display": "6.5.8",
+ "@pixi/math": "6.5.8",
+ "@pixi/ticker": "6.5.8",
+ "@pixi/utils": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/loaders": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/loaders/-/loaders-6.5.8.tgz",
+ "integrity": "sha512-mj11UPKsqWaTEPMpCnFugr6heKkQeNFuVSddSwE8crg19l46zcMhk3ucpQX15RDpAdDJjtl3OraevQCHHbNENw==",
+ "peerDependencies": {
+ "@pixi/constants": "6.5.8",
+ "@pixi/core": "6.5.8",
+ "@pixi/utils": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/math": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/math/-/math-6.5.8.tgz",
+ "integrity": "sha512-9493KEH5ITnjOZvQZbaU22lD0kcg/XhNh+309KYfwFX787zA1BN/7is06oHEgHBDb2NemqioYi6sw1WnECgQig=="
+ },
+ "node_modules/@pixi/mesh": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/mesh/-/mesh-6.5.8.tgz",
+ "integrity": "sha512-iZZGkh8QBhnfMEgpJsuwemFZZVatodckCgj7N8t1hyHEf0aOWEA6wp5N0Osa3mhltokl7BGnZZLxaR8NtjaiEQ==",
+ "peerDependencies": {
+ "@pixi/constants": "6.5.8",
+ "@pixi/core": "6.5.8",
+ "@pixi/display": "6.5.8",
+ "@pixi/math": "6.5.8",
+ "@pixi/settings": "6.5.8",
+ "@pixi/utils": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/mesh-extras": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/mesh-extras/-/mesh-extras-6.5.8.tgz",
+ "integrity": "sha512-eU2I53yZUFxKbTYZvyRfUcdina3WOl87fyqYwAoaHosU9VgbFl16YADKTGV+NflNp6RCTwU/UIPZ1T19W/iysw==",
+ "peerDependencies": {
+ "@pixi/constants": "6.5.8",
+ "@pixi/core": "6.5.8",
+ "@pixi/math": "6.5.8",
+ "@pixi/mesh": "6.5.8",
+ "@pixi/utils": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/mixin-cache-as-bitmap": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/mixin-cache-as-bitmap/-/mixin-cache-as-bitmap-6.5.8.tgz",
+ "integrity": "sha512-5TTv4w8v7guI6z3gKz5ppUCbNMRw+8RRNru/aq65qUl6kcUaJiYwQdBFJ/vJwpI9ePEScWrCuLVEc8QtX6xjNw==",
+ "peerDependencies": {
+ "@pixi/constants": "6.5.8",
+ "@pixi/core": "6.5.8",
+ "@pixi/display": "6.5.8",
+ "@pixi/math": "6.5.8",
+ "@pixi/settings": "6.5.8",
+ "@pixi/sprite": "6.5.8",
+ "@pixi/utils": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/mixin-get-child-by-name": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/mixin-get-child-by-name/-/mixin-get-child-by-name-6.5.8.tgz",
+ "integrity": "sha512-b15HTdHpW4ErDBpf7wm1vvWHrTv5kQzElXrwAPBCnLgvronfSL9mL7npOUkZOybUorCoEBq/7oNVjkimsQc5gw==",
+ "peerDependencies": {
+ "@pixi/display": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/mixin-get-global-position": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/mixin-get-global-position/-/mixin-get-global-position-6.5.8.tgz",
+ "integrity": "sha512-Y5epEW5mRrgpDOHvfc92t0PaBgboBKXR4n/AzOOFt0h9GRNTmVKYBpUQPp/HO+r1Bxq+XbaGm1CyfkjUUxnORA==",
+ "peerDependencies": {
+ "@pixi/display": "6.5.8",
+ "@pixi/math": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/particle-container": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/particle-container/-/particle-container-6.5.8.tgz",
+ "integrity": "sha512-wc4j84PssPWmZLpOJTLLC7MftCULzkQMAfVlwOERhNTZ+6E1LIKw91wDWZe9LQ/20iarzQwQXo0a4uNlJlhnVQ==",
+ "peerDependencies": {
+ "@pixi/constants": "6.5.8",
+ "@pixi/core": "6.5.8",
+ "@pixi/display": "6.5.8",
+ "@pixi/math": "6.5.8",
+ "@pixi/sprite": "6.5.8",
+ "@pixi/utils": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/polyfill": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/polyfill/-/polyfill-6.5.8.tgz",
+ "integrity": "sha512-z2klHelxTZExMyO4oiLdxJMGzzXnToEIDn7Dwfy3FY+98LbxSa2dVFCgzDsYeiiS8fSMsni2Ru7aZT/DFsRDcA==",
+ "dependencies": {
+ "object-assign": "^4.1.1",
+ "promise-polyfill": "^8.2.0"
+ }
+ },
+ "node_modules/@pixi/prepare": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/prepare/-/prepare-6.5.8.tgz",
+ "integrity": "sha512-anrAcjX3r9ZzK/L6Fw7GhE1pCkjhSfBsxUTlVhuRKJPFC+A3BNpZCwy3GzyvHP4ocl8wvUMzuz5BB5l0AoBCFw==",
+ "peerDependencies": {
+ "@pixi/core": "6.5.8",
+ "@pixi/display": "6.5.8",
+ "@pixi/graphics": "6.5.8",
+ "@pixi/settings": "6.5.8",
+ "@pixi/text": "6.5.8",
+ "@pixi/ticker": "6.5.8",
+ "@pixi/utils": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/runner": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/runner/-/runner-6.5.8.tgz",
+ "integrity": "sha512-/9KVgQjTKiBa1qHdNmhP9I+AHgC/Eu9QiKcc+oakLCJtpYi79lx+nDFrpLUamIi2c7lP0hDWVe0XqlQeYmSwag=="
+ },
+ "node_modules/@pixi/settings": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/settings/-/settings-6.5.8.tgz",
+ "integrity": "sha512-gmnwHkg9+tlQRuFNOdimzl73Dup2fdEo/VYaF7spT+8womE4KWAvARCBMqY/10aAx1iYeYuo5av/RfqrePB5Hg==",
+ "peerDependencies": {
+ "@pixi/constants": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/sprite": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/sprite/-/sprite-6.5.8.tgz",
+ "integrity": "sha512-ywvbrNgjK+K93X9cvHtDCnsBtU7B9JD/3wg+1G6v1Ktrr2E1gwVIQK1NANBrjzt6cYGphz5EqGAW68d0rMBliw==",
+ "peerDependencies": {
+ "@pixi/constants": "6.5.8",
+ "@pixi/core": "6.5.8",
+ "@pixi/display": "6.5.8",
+ "@pixi/math": "6.5.8",
+ "@pixi/settings": "6.5.8",
+ "@pixi/utils": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/sprite-animated": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/sprite-animated/-/sprite-animated-6.5.8.tgz",
+ "integrity": "sha512-woPT2cF1BaC0PDWdDrqJ0+DYcyIeXzZLq6bVx2YYia3+jJao1Zjmz1ns5e7YMUTEG7DoVFfhO6CC81YimsMG5w==",
+ "peerDependencies": {
+ "@pixi/core": "6.5.8",
+ "@pixi/sprite": "6.5.8",
+ "@pixi/ticker": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/sprite-tiling": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/sprite-tiling/-/sprite-tiling-6.5.8.tgz",
+ "integrity": "sha512-PG3tiWI6uUest/d7HAz4/3I8NjpYyeMUL2WDy86nMXCJ6bLdTs/s9Nq3DLckaUsyIMTGsVbj/BXjE8LP1WDTog==",
+ "peerDependencies": {
+ "@pixi/constants": "6.5.8",
+ "@pixi/core": "6.5.8",
+ "@pixi/display": "6.5.8",
+ "@pixi/math": "6.5.8",
+ "@pixi/sprite": "6.5.8",
+ "@pixi/utils": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/spritesheet": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/spritesheet/-/spritesheet-6.5.8.tgz",
+ "integrity": "sha512-WiJd4fKpSitD3A+/u5q8IPoHXMFT8++bsluhuJvDwzo//s0PHb9qExlF2xos7zUmekmydEFMkDnrl4+lWn2cyg==",
+ "peerDependencies": {
+ "@pixi/core": "6.5.8",
+ "@pixi/loaders": "6.5.8",
+ "@pixi/math": "6.5.8",
+ "@pixi/utils": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/text": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/text/-/text-6.5.8.tgz",
+ "integrity": "sha512-7AZPj5+vWcUjK0QzQ3ehiEwEqywiWR8NhDmnnN5nRNHR9u5IOOnqCQtBTdDffYPN0uMgCi8MzUPwTJhGuyOeww==",
+ "peerDependencies": {
+ "@pixi/core": "6.5.8",
+ "@pixi/math": "6.5.8",
+ "@pixi/settings": "6.5.8",
+ "@pixi/sprite": "6.5.8",
+ "@pixi/utils": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/text-bitmap": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/text-bitmap/-/text-bitmap-6.5.8.tgz",
+ "integrity": "sha512-6VxejDc0gOu5HFN06m6i94xBZHdZ728iao8q+hEOjavGR5i2Pv3xseuke1qY0iN4q6Z+wTkcmoK5BfEVi2ujdQ==",
+ "peerDependencies": {
+ "@pixi/constants": "6.5.8",
+ "@pixi/core": "6.5.8",
+ "@pixi/display": "6.5.8",
+ "@pixi/loaders": "6.5.8",
+ "@pixi/math": "6.5.8",
+ "@pixi/mesh": "6.5.8",
+ "@pixi/settings": "6.5.8",
+ "@pixi/text": "6.5.8",
+ "@pixi/utils": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/ticker": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/ticker/-/ticker-6.5.8.tgz",
+ "integrity": "sha512-7VKq5hfnRDSv6a16pATqZAmpQfEu4G171iUTloy3QZfbnPw0s3JervZSih1yJJD84GXEF4VzYB26pJ/x3arGjQ==",
+ "peerDependencies": {
+ "@pixi/extensions": "6.5.8",
+ "@pixi/settings": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/utils": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/utils/-/utils-6.5.8.tgz",
+ "integrity": "sha512-zLnvmVQBWPDnwkfvrSpBBF2XpWSMt+kQAsX562eqjuME63ic9M6fK4u/IaA8csdlG2wtcjBvSYWrpWmPq0bWag==",
+ "dependencies": {
+ "@types/earcut": "^2.1.0",
+ "earcut": "^2.2.4",
+ "eventemitter3": "^3.1.0",
+ "url": "^0.11.0"
+ },
+ "peerDependencies": {
+ "@pixi/constants": "6.5.8",
+ "@pixi/settings": "6.5.8"
+ }
+ },
+ "node_modules/@pixi/utils/node_modules/eventemitter3": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz",
+ "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q=="
+ },
+ "node_modules/@types/body-parser": {
+ "version": "1.19.2",
+ "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz",
+ "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==",
+ "dev": true,
+ "dependencies": {
+ "@types/connect": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/bonjour": {
+ "version": "3.5.10",
+ "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz",
+ "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/connect": {
+ "version": "3.4.35",
+ "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz",
+ "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/connect-history-api-fallback": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz",
+ "integrity": "sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==",
+ "dev": true,
+ "dependencies": {
+ "@types/express-serve-static-core": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/earcut": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@types/earcut/-/earcut-2.1.1.tgz",
+ "integrity": "sha512-w8oigUCDjElRHRRrMvn/spybSMyX8MTkKA5Dv+tS1IE/TgmNZPqUYtvYBXGY8cieSE66gm+szeK+bnbxC2xHTQ=="
+ },
+ "node_modules/@types/eslint": {
+ "version": "8.4.2",
+ "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.2.tgz",
+ "integrity": "sha512-Z1nseZON+GEnFjJc04sv4NSALGjhFwy6K0HXt7qsn5ArfAKtb63dXNJHf+1YW6IpOIYRBGUbu3GwJdj8DGnCjA==",
+ "dev": true,
+ "dependencies": {
+ "@types/estree": "*",
+ "@types/json-schema": "*"
+ }
+ },
+ "node_modules/@types/eslint-scope": {
+ "version": "3.7.3",
+ "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz",
+ "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==",
+ "dev": true,
+ "dependencies": {
+ "@types/eslint": "*",
+ "@types/estree": "*"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "0.0.51",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz",
+ "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==",
+ "dev": true
+ },
+ "node_modules/@types/express": {
+ "version": "4.17.13",
+ "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz",
+ "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==",
+ "dev": true,
+ "dependencies": {
+ "@types/body-parser": "*",
+ "@types/express-serve-static-core": "^4.17.18",
+ "@types/qs": "*",
+ "@types/serve-static": "*"
+ }
+ },
+ "node_modules/@types/express-serve-static-core": {
+ "version": "4.17.28",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz",
+ "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*",
+ "@types/qs": "*",
+ "@types/range-parser": "*"
+ }
+ },
+ "node_modules/@types/http-proxy": {
+ "version": "1.17.9",
+ "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.9.tgz",
+ "integrity": "sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "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/@types/mime": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz",
+ "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==",
+ "dev": true
+ },
+ "node_modules/@types/node": {
+ "version": "17.0.38",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.38.tgz",
+ "integrity": "sha512-5jY9RhV7c0Z4Jy09G+NIDTsCZ5G0L5n+Z+p+Y7t5VJHM30bgwzSjVtlcBxqAj+6L/swIlvtOSzr8rBk/aNyV2g==",
+ "dev": true
+ },
+ "node_modules/@types/offscreencanvas": {
+ "version": "2019.7.0",
+ "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.0.tgz",
+ "integrity": "sha512-PGcyveRIpL1XIqK8eBsmRBt76eFgtzuPiSTyKHZxnGemp2yzGzWpjYKAfK3wIMiU7eH+851yEpiuP8JZerTmWg=="
+ },
+ "node_modules/@types/qs": {
+ "version": "6.9.7",
+ "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
+ "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==",
+ "dev": true
+ },
+ "node_modules/@types/range-parser": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz",
+ "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==",
+ "dev": true
+ },
+ "node_modules/@types/retry": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz",
+ "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==",
+ "dev": true
+ },
+ "node_modules/@types/seedrandom": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-3.0.2.tgz",
+ "integrity": "sha512-YPLqEOo0/X8JU3rdiq+RgUKtQhQtrppE766y7vMTu8dGML7TVtZNiiiaC/hhU9Zqw9UYopXxhuWWENclMVBwKQ==",
+ "dev": true
+ },
+ "node_modules/@types/serve-index": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz",
+ "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==",
+ "dev": true,
+ "dependencies": {
+ "@types/express": "*"
+ }
+ },
+ "node_modules/@types/serve-static": {
+ "version": "1.13.10",
+ "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz",
+ "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/mime": "^1",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/sockjs": {
+ "version": "0.3.33",
+ "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz",
+ "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/stats.js": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.0.tgz",
+ "integrity": "sha512-9w+a7bR8PeB0dCT/HBULU2fMqf6BAzvKbxFboYhmDtDkKPiyXYbjoe2auwsXlEFI7CFNMF1dCv3dFH5Poy9R1w==",
+ "dev": true
+ },
+ "node_modules/@types/ws": {
+ "version": "8.5.3",
+ "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz",
+ "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@webassemblyjs/ast": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz",
+ "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==",
+ "dev": true,
+ "dependencies": {
+ "@webassemblyjs/helper-numbers": "1.11.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.11.1"
+ }
+ },
+ "node_modules/@webassemblyjs/floating-point-hex-parser": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz",
+ "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==",
+ "dev": true
+ },
+ "node_modules/@webassemblyjs/helper-api-error": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz",
+ "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==",
+ "dev": true
+ },
+ "node_modules/@webassemblyjs/helper-buffer": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz",
+ "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==",
+ "dev": true
+ },
+ "node_modules/@webassemblyjs/helper-numbers": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz",
+ "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==",
+ "dev": true,
+ "dependencies": {
+ "@webassemblyjs/floating-point-hex-parser": "1.11.1",
+ "@webassemblyjs/helper-api-error": "1.11.1",
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "node_modules/@webassemblyjs/helper-wasm-bytecode": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz",
+ "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==",
+ "dev": true
+ },
+ "node_modules/@webassemblyjs/helper-wasm-section": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz",
+ "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==",
+ "dev": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.11.1",
+ "@webassemblyjs/helper-buffer": "1.11.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
+ "@webassemblyjs/wasm-gen": "1.11.1"
+ }
+ },
+ "node_modules/@webassemblyjs/ieee754": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz",
+ "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==",
+ "dev": true,
+ "dependencies": {
+ "@xtuc/ieee754": "^1.2.0"
+ }
+ },
+ "node_modules/@webassemblyjs/leb128": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz",
+ "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==",
+ "dev": true,
+ "dependencies": {
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "node_modules/@webassemblyjs/utf8": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz",
+ "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==",
+ "dev": true
+ },
+ "node_modules/@webassemblyjs/wasm-edit": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz",
+ "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==",
+ "dev": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.11.1",
+ "@webassemblyjs/helper-buffer": "1.11.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
+ "@webassemblyjs/helper-wasm-section": "1.11.1",
+ "@webassemblyjs/wasm-gen": "1.11.1",
+ "@webassemblyjs/wasm-opt": "1.11.1",
+ "@webassemblyjs/wasm-parser": "1.11.1",
+ "@webassemblyjs/wast-printer": "1.11.1"
+ }
+ },
+ "node_modules/@webassemblyjs/wasm-gen": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz",
+ "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==",
+ "dev": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.11.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
+ "@webassemblyjs/ieee754": "1.11.1",
+ "@webassemblyjs/leb128": "1.11.1",
+ "@webassemblyjs/utf8": "1.11.1"
+ }
+ },
+ "node_modules/@webassemblyjs/wasm-opt": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz",
+ "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==",
+ "dev": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.11.1",
+ "@webassemblyjs/helper-buffer": "1.11.1",
+ "@webassemblyjs/wasm-gen": "1.11.1",
+ "@webassemblyjs/wasm-parser": "1.11.1"
+ }
+ },
+ "node_modules/@webassemblyjs/wasm-parser": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz",
+ "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==",
+ "dev": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.11.1",
+ "@webassemblyjs/helper-api-error": "1.11.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
+ "@webassemblyjs/ieee754": "1.11.1",
+ "@webassemblyjs/leb128": "1.11.1",
+ "@webassemblyjs/utf8": "1.11.1"
+ }
+ },
+ "node_modules/@webassemblyjs/wast-printer": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz",
+ "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==",
+ "dev": true,
+ "dependencies": {
+ "@webassemblyjs/ast": "1.11.1",
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "node_modules/@webpack-cli/configtest": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz",
+ "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==",
+ "dev": true,
+ "peerDependencies": {
+ "webpack": "4.x.x || 5.x.x",
+ "webpack-cli": "4.x.x"
+ }
+ },
+ "node_modules/@webpack-cli/info": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.5.0.tgz",
+ "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==",
+ "dev": true,
+ "dependencies": {
+ "envinfo": "^7.7.3"
+ },
+ "peerDependencies": {
+ "webpack-cli": "4.x.x"
+ }
+ },
+ "node_modules/@webpack-cli/serve": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz",
+ "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==",
+ "dev": true,
+ "peerDependencies": {
+ "webpack-cli": "4.x.x"
+ },
+ "peerDependenciesMeta": {
+ "webpack-dev-server": {
+ "optional": true
+ }
+ }
+ },
+ "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
+ },
+ "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
+ },
+ "node_modules/accepts": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
+ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+ "dev": true,
+ "dependencies": {
+ "mime-types": "~2.1.34",
+ "negotiator": "0.6.3"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.7.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz",
+ "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-import-assertions": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz",
+ "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==",
+ "dev": true,
+ "peerDependencies": {
+ "acorn": "^8"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "8.11.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
+ "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
+ "dev": true,
+ "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/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,
+ "dependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "ajv": {
+ "optional": true
+ }
+ }
+ },
+ "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,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3"
+ },
+ "peerDependencies": {
+ "ajv": "^8.8.2"
+ }
+ },
+ "node_modules/ansi-html-community": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz",
+ "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==",
+ "dev": true,
+ "engines": [
+ "node >= 0.8.0"
+ ],
+ "bin": {
+ "ansi-html": "bin/ansi-html"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
+ "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
+ "dev": true,
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/array-flatten": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz",
+ "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==",
+ "dev": 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/batch": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
+ "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/body-parser": {
+ "version": "1.20.0",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz",
+ "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==",
+ "dev": true,
+ "dependencies": {
+ "bytes": "3.1.2",
+ "content-type": "~1.0.4",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "on-finished": "2.4.1",
+ "qs": "6.10.3",
+ "raw-body": "2.5.1",
+ "type-is": "~1.6.18",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/body-parser/node_modules/bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/bonjour-service": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.0.12.tgz",
+ "integrity": "sha512-pMmguXYCu63Ug37DluMKEHdxc+aaIf/ay4YbF8Gxtba+9d3u+rmEWy61VK3Z3hp8Rskok3BunHYnG0dUHAsblw==",
+ "dev": true,
+ "dependencies": {
+ "array-flatten": "^2.1.2",
+ "dns-equal": "^1.0.0",
+ "fast-deep-equal": "^3.1.3",
+ "multicast-dns": "^7.2.4"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.20.3",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz",
+ "integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ }
+ ],
+ "dependencies": {
+ "caniuse-lite": "^1.0.30001332",
+ "electron-to-chromium": "^1.4.118",
+ "escalade": "^3.1.1",
+ "node-releases": "^2.0.3",
+ "picocolors": "^1.0.0"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "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/bytes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
+ "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.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==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001344",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001344.tgz",
+ "integrity": "sha512-0ZFjnlCaXNOAYcV7i+TtdKBp0L/3XEU2MF/x6Du1lrh+SRX4IfzIVL4HNJg5pB2PmFb8rszIGyOvsZnqqRoc2g==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ }
+ ]
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "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/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/"
+ }
+ ],
+ "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/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==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0"
+ }
+ },
+ "node_modules/clone-deep": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
+ "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
+ "dev": true,
+ "dependencies": {
+ "is-plain-object": "^2.0.4",
+ "kind-of": "^6.0.2",
+ "shallow-clone": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "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==",
+ "dev": true
+ },
+ "node_modules/colorette": {
+ "version": "2.0.16",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz",
+ "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==",
+ "dev": true
+ },
+ "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
+ },
+ "node_modules/compressible": {
+ "version": "2.0.18",
+ "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
+ "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==",
+ "dev": true,
+ "dependencies": {
+ "mime-db": ">= 1.43.0 < 2"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/compression": {
+ "version": "1.7.4",
+ "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz",
+ "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==",
+ "dev": true,
+ "dependencies": {
+ "accepts": "~1.3.5",
+ "bytes": "3.0.0",
+ "compressible": "~2.0.16",
+ "debug": "2.6.9",
+ "on-headers": "~1.0.2",
+ "safe-buffer": "5.1.2",
+ "vary": "~1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/compression/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ },
+ "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/connect-history-api-fallback": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz",
+ "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/content-disposition": {
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
+ "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "5.2.1"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/content-type": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
+ "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
+ "dev": true
+ },
+ "node_modules/copy-webpack-plugin": {
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz",
+ "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==",
+ "dev": true,
+ "dependencies": {
+ "fast-glob": "^3.2.11",
+ "glob-parent": "^6.0.1",
+ "globby": "^13.1.1",
+ "normalize-path": "^3.0.0",
+ "schema-utils": "^4.0.0",
+ "serialize-javascript": "^6.0.0"
+ },
+ "engines": {
+ "node": ">= 14.15.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "^5.1.0"
+ }
+ },
+ "node_modules/core-util-is": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/default-gateway": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz",
+ "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==",
+ "dev": true,
+ "dependencies": {
+ "execa": "^5.0.0"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/define-lazy-prop": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
+ "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/destroy": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
+ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/detect-node": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz",
+ "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==",
+ "dev": true
+ },
+ "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,
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/dns-equal": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
+ "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==",
+ "dev": true
+ },
+ "node_modules/dns-packet": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.3.1.tgz",
+ "integrity": "sha512-spBwIj0TK0Ey3666GwIdWVfUpLyubpU53BTCu8iPn4r4oXd9O14Hjg3EHw3ts2oed77/SeckunUYCyRlSngqHw==",
+ "dev": true,
+ "dependencies": {
+ "@leichtgewicht/ip-codec": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/earcut": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz",
+ "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ=="
+ },
+ "node_modules/ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+ "dev": true
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.4.143",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.143.tgz",
+ "integrity": "sha512-2hIgvu0+pDfXIqmVmV5X6iwMjQ2KxDsWKwM+oI1fABEOy/Dqmll0QJRmIQ3rm+XaoUa/qKrmy5h7LSTFQ6Ldzg==",
+ "dev": true
+ },
+ "node_modules/encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/enhanced-resolve": {
+ "version": "5.10.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz",
+ "integrity": "sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.2.4",
+ "tapable": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/envinfo": {
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz",
+ "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==",
+ "dev": true,
+ "bin": {
+ "envinfo": "dist/cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/es-module-lexer": {
+ "version": "0.9.3",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz",
+ "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==",
+ "dev": true
+ },
+ "node_modules/escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+ "dev": true
+ },
+ "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"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "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,
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esrecurse/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,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/eventemitter3": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
+ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
+ "dev": true
+ },
+ "node_modules/events": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.x"
+ }
+ },
+ "node_modules/execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/express": {
+ "version": "4.18.1",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz",
+ "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==",
+ "dev": true,
+ "dependencies": {
+ "accepts": "~1.3.8",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.20.0",
+ "content-disposition": "0.5.4",
+ "content-type": "~1.0.4",
+ "cookie": "0.5.0",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "1.2.0",
+ "fresh": "0.5.2",
+ "http-errors": "2.0.0",
+ "merge-descriptors": "1.0.1",
+ "methods": "~1.1.2",
+ "on-finished": "2.4.1",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "0.1.7",
+ "proxy-addr": "~2.0.7",
+ "qs": "6.10.3",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.2.1",
+ "send": "0.18.0",
+ "serve-static": "1.15.0",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "type-is": "~1.6.18",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.10.0"
+ }
+ },
+ "node_modules/express/node_modules/array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
+ "dev": true
+ },
+ "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-glob": {
+ "version": "3.2.11",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
+ "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "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,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "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/fastest-levenshtein": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz",
+ "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==",
+ "dev": true
+ },
+ "node_modules/fastq": {
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
+ "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==",
+ "dev": true,
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/faye-websocket": {
+ "version": "0.11.4",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz",
+ "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==",
+ "dev": true,
+ "dependencies": {
+ "websocket-driver": ">=0.5.1"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/finalhandler": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
+ "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
+ "dev": true,
+ "dependencies": {
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "on-finished": "2.4.1",
+ "parseurl": "~1.3.3",
+ "statuses": "2.0.1",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "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,
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/follow-redirects": {
+ "version": "1.15.1",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz",
+ "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/forwarded": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fs-monkey": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz",
+ "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
+ "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "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/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,
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "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
+ },
+ "node_modules/globby": {
+ "version": "13.1.1",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.1.tgz",
+ "integrity": "sha512-XMzoDZbGZ37tufiv7g0N4F/zp3zkwdFtVbV3EHsVl1KQr4RPLfNoT068/97RPshz2J5xYNEjLKKBKaGHifBd3Q==",
+ "dev": true,
+ "dependencies": {
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.11",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^4.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "node_modules/handle-thing": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz",
+ "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==",
+ "dev": true
+ },
+ "node_modules/has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4.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==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hash-wasm": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/hash-wasm/-/hash-wasm-4.12.0.tgz",
+ "integrity": "sha512-+/2B2rYLb48I/evdOIhP+K/DD2ca2fgBjp6O+GBEnCDk2e4rpeXIK8GvIyRPjTezgmWn9gmKwkQjjx6BtqDHVQ==",
+ "license": "MIT"
+ },
+ "node_modules/hpack.js": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
+ "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.1",
+ "obuf": "^1.0.0",
+ "readable-stream": "^2.0.1",
+ "wbuf": "^1.1.0"
+ }
+ },
+ "node_modules/hpack.js/node_modules/readable-stream": {
+ "version": "2.3.7",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+ "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+ "dev": true,
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/hpack.js/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ },
+ "node_modules/hpack.js/node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/html-entities": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz",
+ "integrity": "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==",
+ "dev": true
+ },
+ "node_modules/http-deceiver": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
+ "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==",
+ "dev": true
+ },
+ "node_modules/http-errors": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
+ "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
+ "dev": true,
+ "dependencies": {
+ "depd": "2.0.0",
+ "inherits": "2.0.4",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "toidentifier": "1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/http-parser-js": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.6.tgz",
+ "integrity": "sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA==",
+ "dev": true
+ },
+ "node_modules/http-proxy": {
+ "version": "1.18.1",
+ "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
+ "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
+ "dev": true,
+ "dependencies": {
+ "eventemitter3": "^4.0.0",
+ "follow-redirects": "^1.0.0",
+ "requires-port": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/http-proxy-middleware": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz",
+ "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==",
+ "dev": true,
+ "dependencies": {
+ "@types/http-proxy": "^1.17.8",
+ "http-proxy": "^1.18.1",
+ "is-glob": "^4.0.1",
+ "is-plain-obj": "^3.0.0",
+ "micromatch": "^4.0.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "@types/express": "^4.17.13"
+ },
+ "peerDependenciesMeta": {
+ "@types/express": {
+ "optional": 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,
+ "engines": {
+ "node": ">=10.17.0"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dev": true,
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
+ "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-local": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz",
+ "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==",
+ "dev": true,
+ "dependencies": {
+ "pkg-dir": "^4.2.0",
+ "resolve-cwd": "^3.0.0"
+ },
+ "bin": {
+ "import-local-fixture": "fixtures/cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "node_modules/interpret": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz",
+ "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/ipaddr.js": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz",
+ "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==",
+ "dev": true,
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "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,
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz",
+ "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==",
+ "dev": true,
+ "dependencies": {
+ "has": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-docker": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
+ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
+ "dev": true,
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=0.10.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==",
+ "dev": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-plain-obj": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz",
+ "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "isobject": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-wsl": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
+ "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+ "dev": true,
+ "dependencies": {
+ "is-docker": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.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==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ }
+ },
+ "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,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "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": "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/kind-of": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/lil-gui": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/lil-gui/-/lil-gui-0.17.0.tgz",
+ "integrity": "sha512-MVBHmgY+uEbmJNApAaPbtvNh1RCAeMnKym82SBjtp5rODTYKWtM+MXHCifLe2H2Ti1HuBGBtK/5SyG4ShQ3pUQ=="
+ },
+ "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==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.11.5"
+ }
+ },
+ "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,
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/memfs": {
+ "version": "3.4.4",
+ "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.4.tgz",
+ "integrity": "sha512-W4gHNUE++1oSJVn8Y68jPXi+mkx3fXR5ITE/Ubz6EQ3xRpCN5k2CQ4AUR8094Z7211F876TyoBACGsIveqgiGA==",
+ "dev": true,
+ "dependencies": {
+ "fs-monkey": "1.0.3"
+ },
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/merge-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+ "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dev": true,
+ "dependencies": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "dev": true,
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "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==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/minimalistic-assert": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
+ "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
+ "dev": true
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "dev": true
+ },
+ "node_modules/multicast-dns": {
+ "version": "7.2.5",
+ "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz",
+ "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==",
+ "dev": true,
+ "dependencies": {
+ "dns-packet": "^5.2.2",
+ "thunky": "^1.0.2"
+ },
+ "bin": {
+ "multicast-dns": "cli.js"
+ }
+ },
+ "node_modules/negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "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
+ },
+ "node_modules/node-forge": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
+ "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6.13.0"
+ }
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz",
+ "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==",
+ "dev": true
+ },
+ "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,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "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,
+ "dependencies": {
+ "path-key": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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.2",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
+ "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/obuf": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
+ "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==",
+ "dev": true
+ },
+ "node_modules/on-finished": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+ "dev": true,
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/on-headers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
+ "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "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,
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "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,
+ "dependencies": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/open": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz",
+ "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==",
+ "dev": true,
+ "dependencies": {
+ "define-lazy-prop": "^2.0.0",
+ "is-docker": "^2.1.1",
+ "is-wsl": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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,
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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,
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/p-retry": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz",
+ "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/retry": "0.12.0",
+ "retry": "^0.13.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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-to-regexp": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+ "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==",
+ "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,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+ "dev": true
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pixi-viewport": {
+ "version": "4.37.0",
+ "resolved": "https://registry.npmjs.org/pixi-viewport/-/pixi-viewport-4.37.0.tgz",
+ "integrity": "sha512-bF22o1WbWeQ3TTHnxh5MYPzjXiKAG2ezAV6rm1oaEbA66hZAAU6lCs7BgwmEBiZKgHNGko1bIJQUSe7cXWJVCw==",
+ "peerDependencies": {
+ "@pixi/display": "^6.5.7",
+ "@pixi/interaction": "^6.5.7",
+ "@pixi/math": "^6.5.7",
+ "@pixi/ticker": "^6.5.7"
+ }
+ },
+ "node_modules/pixi.js": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/pixi.js/-/pixi.js-6.5.8.tgz",
+ "integrity": "sha512-TAovIMCvKiWlonyAEbStOSq2+GZliRgs+Pqlavffa/D0Rmvmb78bytWRxgonGx1qkg7G8W7eIbF55tFP4a5Krw==",
+ "dependencies": {
+ "@pixi/accessibility": "6.5.8",
+ "@pixi/app": "6.5.8",
+ "@pixi/compressed-textures": "6.5.8",
+ "@pixi/constants": "6.5.8",
+ "@pixi/core": "6.5.8",
+ "@pixi/display": "6.5.8",
+ "@pixi/extensions": "6.5.8",
+ "@pixi/extract": "6.5.8",
+ "@pixi/filter-alpha": "6.5.8",
+ "@pixi/filter-blur": "6.5.8",
+ "@pixi/filter-color-matrix": "6.5.8",
+ "@pixi/filter-displacement": "6.5.8",
+ "@pixi/filter-fxaa": "6.5.8",
+ "@pixi/filter-noise": "6.5.8",
+ "@pixi/graphics": "6.5.8",
+ "@pixi/interaction": "6.5.8",
+ "@pixi/loaders": "6.5.8",
+ "@pixi/math": "6.5.8",
+ "@pixi/mesh": "6.5.8",
+ "@pixi/mesh-extras": "6.5.8",
+ "@pixi/mixin-cache-as-bitmap": "6.5.8",
+ "@pixi/mixin-get-child-by-name": "6.5.8",
+ "@pixi/mixin-get-global-position": "6.5.8",
+ "@pixi/particle-container": "6.5.8",
+ "@pixi/polyfill": "6.5.8",
+ "@pixi/prepare": "6.5.8",
+ "@pixi/runner": "6.5.8",
+ "@pixi/settings": "6.5.8",
+ "@pixi/sprite": "6.5.8",
+ "@pixi/sprite-animated": "6.5.8",
+ "@pixi/sprite-tiling": "6.5.8",
+ "@pixi/spritesheet": "6.5.8",
+ "@pixi/text": "6.5.8",
+ "@pixi/text-bitmap": "6.5.8",
+ "@pixi/ticker": "6.5.8",
+ "@pixi/utils": "6.5.8"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/pixijs"
+ }
+ },
+ "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,
+ "dependencies": {
+ "find-up": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+ "dev": true
+ },
+ "node_modules/promise-polyfill": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.2.3.tgz",
+ "integrity": "sha512-Og0+jCRQetV84U8wVjMNccfGCnMQ9mGs9Hv78QFe+pSDD3gWTpz0y+1QCuxy5d/vBFuZ3iwP2eycAkvqIMPmWg=="
+ },
+ "node_modules/proxy-addr": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+ "dev": true,
+ "dependencies": {
+ "forwarded": "0.2.0",
+ "ipaddr.js": "1.9.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/proxy-addr/node_modules/ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/qs": {
+ "version": "6.10.3",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
+ "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==",
+ "dev": true,
+ "dependencies": {
+ "side-channel": "^1.0.4"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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.",
+ "engines": {
+ "node": ">=0.4.x"
+ }
+ },
+ "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/randombytes": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "node_modules/range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/raw-body": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
+ "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
+ "dev": true,
+ "dependencies": {
+ "bytes": "3.1.2",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/raw-body/node_modules/bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dev": true,
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/rechoir": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz",
+ "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==",
+ "dev": true,
+ "dependencies": {
+ "resolve": "^1.9.0"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/requires-port": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
+ "dev": true
+ },
+ "node_modules/resolve": {
+ "version": "1.22.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
+ "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==",
+ "dev": true,
+ "dependencies": {
+ "is-core-module": "^2.8.1",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-cwd": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+ "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
+ "dev": true,
+ "dependencies": {
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/retry": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
+ "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true,
+ "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/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/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==",
+ "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/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/schema-utils": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz",
+ "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==",
+ "dev": true,
+ "dependencies": {
+ "@types/json-schema": "^7.0.9",
+ "ajv": "^8.8.0",
+ "ajv-formats": "^2.1.1",
+ "ajv-keywords": "^5.0.0"
+ },
+ "engines": {
+ "node": ">= 12.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
+ "node_modules/seedrandom": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz",
+ "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg=="
+ },
+ "node_modules/select-hose": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
+ "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=",
+ "dev": true
+ },
+ "node_modules/selfsigned": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz",
+ "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==",
+ "dev": true,
+ "dependencies": {
+ "node-forge": "^1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.3.7",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+ "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/send": {
+ "version": "0.18.0",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
+ "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
+ "dev": true,
+ "dependencies": {
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "2.0.0",
+ "mime": "1.6.0",
+ "ms": "2.1.3",
+ "on-finished": "2.4.1",
+ "range-parser": "~1.2.1",
+ "statuses": "2.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/send/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/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/serve-index": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
+ "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=",
+ "dev": true,
+ "dependencies": {
+ "accepts": "~1.3.4",
+ "batch": "0.6.1",
+ "debug": "2.6.9",
+ "escape-html": "~1.0.3",
+ "http-errors": "~1.6.2",
+ "mime-types": "~2.1.17",
+ "parseurl": "~1.3.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/serve-index/node_modules/depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/serve-index/node_modules/http-errors": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
+ "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==",
+ "dev": true,
+ "dependencies": {
+ "depd": "~1.1.2",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.1.0",
+ "statuses": ">= 1.4.0 < 2"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/serve-index/node_modules/inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==",
+ "dev": true
+ },
+ "node_modules/serve-index/node_modules/setprototypeof": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
+ "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
+ "dev": true
+ },
+ "node_modules/serve-index/node_modules/statuses": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/serve-static": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
+ "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
+ "dev": true,
+ "dependencies": {
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "0.18.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/setprototypeof": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+ "dev": true
+ },
+ "node_modules/shallow-clone": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
+ "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
+ "dev": true,
+ "dependencies": {
+ "kind-of": "^6.0.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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,
+ "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,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.0",
+ "get-intrinsic": "^1.0.2",
+ "object-inspect": "^1.9.0"
+ },
+ "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
+ },
+ "node_modules/slash": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz",
+ "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/sockjs": {
+ "version": "0.3.24",
+ "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz",
+ "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==",
+ "dev": true,
+ "dependencies": {
+ "faye-websocket": "^0.11.3",
+ "uuid": "^8.3.2",
+ "websocket-driver": "^0.7.4"
+ }
+ },
+ "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,
+ "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,
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/spdy": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz",
+ "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^4.1.0",
+ "handle-thing": "^2.0.0",
+ "http-deceiver": "^1.2.7",
+ "select-hose": "^2.0.0",
+ "spdy-transport": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/spdy-transport": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz",
+ "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^4.1.0",
+ "detect-node": "^2.0.4",
+ "hpack.js": "^2.1.6",
+ "obuf": "^1.1.2",
+ "readable-stream": "^3.0.6",
+ "wbuf": "^1.7.3"
+ }
+ },
+ "node_modules/spdy-transport/node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/spdy-transport/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==",
+ "dev": true
+ },
+ "node_modules/spdy/node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/spdy/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==",
+ "dev": true
+ },
+ "node_modules/stats.js": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/stats.js/-/stats.js-0.17.0.tgz",
+ "integrity": "sha1-scPcRtlEmLV4t/05hbgaznExzH0="
+ },
+ "node_modules/statuses": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
+ "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "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==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "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==",
+ "dev": true,
+ "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,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/tapable": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
+ "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/terser": {
+ "version": "5.14.0",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.0.tgz",
+ "integrity": "sha512-JC6qfIEkPBd9j1SMO3Pfn+A6w2kQV54tv+ABQLgZr7dA3k/DL/OBoYSWxzVpZev3J+bUHXfr55L8Mox7AaNo6g==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/terser-webpack-plugin": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz",
+ "integrity": "sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g==",
+ "dev": true,
+ "dependencies": {
+ "jest-worker": "^27.4.5",
+ "schema-utils": "^3.1.1",
+ "serialize-javascript": "^6.0.0",
+ "source-map": "^0.6.1",
+ "terser": "^5.7.2"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ },
+ "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
+ }
+ }
+ },
+ "node_modules/terser-webpack-plugin/node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "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"
+ }
+ },
+ "node_modules/terser-webpack-plugin/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==",
+ "dev": true,
+ "peerDependencies": {
+ "ajv": "^6.9.1"
+ }
+ },
+ "node_modules/terser-webpack-plugin/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/terser-webpack-plugin/node_modules/schema-utils": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
+ "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==",
+ "dev": 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/thunky": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz",
+ "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==",
+ "dev": true
+ },
+ "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,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/toidentifier": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/ts-loader": {
+ "version": "9.4.1",
+ "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.4.1.tgz",
+ "integrity": "sha512-384TYAqGs70rn9F0VBnh6BPTfhga7yFNdC5gXbQpDrBj9/KsT4iRkGqKXhziofHOlE2j6YEaiTYVGKKvPhGWvw==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "enhanced-resolve": "^5.0.0",
+ "micromatch": "^4.0.0",
+ "semver": "^7.3.4"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "typescript": "*",
+ "webpack": "^5.0.0"
+ }
+ },
+ "node_modules/type-is": {
+ "version": "1.6.18",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "dev": true,
+ "dependencies": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "4.8.4",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz",
+ "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==",
+ "dev": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ },
+ "node_modules/unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "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,
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/url": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
+ "integrity": "sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==",
+ "dependencies": {
+ "punycode": "1.3.2",
+ "querystring": "0.2.0"
+ }
+ },
+ "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/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+ "dev": true
+ },
+ "node_modules/utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "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/vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "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,
+ "dependencies": {
+ "glob-to-regexp": "^0.4.1",
+ "graceful-fs": "^4.1.2"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/wbuf": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz",
+ "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==",
+ "dev": true,
+ "dependencies": {
+ "minimalistic-assert": "^1.0.0"
+ }
+ },
+ "node_modules/webpack": {
+ "version": "5.74.0",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz",
+ "integrity": "sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==",
+ "dev": true,
+ "dependencies": {
+ "@types/eslint-scope": "^3.7.3",
+ "@types/estree": "^0.0.51",
+ "@webassemblyjs/ast": "1.11.1",
+ "@webassemblyjs/wasm-edit": "1.11.1",
+ "@webassemblyjs/wasm-parser": "1.11.1",
+ "acorn": "^8.7.1",
+ "acorn-import-assertions": "^1.7.6",
+ "browserslist": "^4.14.5",
+ "chrome-trace-event": "^1.0.2",
+ "enhanced-resolve": "^5.10.0",
+ "es-module-lexer": "^0.9.0",
+ "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.0",
+ "tapable": "^2.1.1",
+ "terser-webpack-plugin": "^5.1.3",
+ "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-cli": {
+ "version": "4.10.0",
+ "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz",
+ "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==",
+ "dev": true,
+ "dependencies": {
+ "@discoveryjs/json-ext": "^0.5.0",
+ "@webpack-cli/configtest": "^1.2.0",
+ "@webpack-cli/info": "^1.5.0",
+ "@webpack-cli/serve": "^1.7.0",
+ "colorette": "^2.0.14",
+ "commander": "^7.0.0",
+ "cross-spawn": "^7.0.3",
+ "fastest-levenshtein": "^1.0.12",
+ "import-local": "^3.0.2",
+ "interpret": "^2.2.0",
+ "rechoir": "^0.7.0",
+ "webpack-merge": "^5.7.3"
+ },
+ "bin": {
+ "webpack-cli": "bin/cli.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "4.x.x || 5.x.x"
+ },
+ "peerDependenciesMeta": {
+ "@webpack-cli/generators": {
+ "optional": true
+ },
+ "@webpack-cli/migrate": {
+ "optional": true
+ },
+ "webpack-bundle-analyzer": {
+ "optional": true
+ },
+ "webpack-dev-server": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/webpack-cli/node_modules/commander": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
+ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/webpack-dev-middleware": {
+ "version": "5.3.3",
+ "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz",
+ "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==",
+ "dev": true,
+ "dependencies": {
+ "colorette": "^2.0.10",
+ "memfs": "^3.4.3",
+ "mime-types": "^2.1.31",
+ "range-parser": "^1.2.1",
+ "schema-utils": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 12.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "^4.0.0 || ^5.0.0"
+ }
+ },
+ "node_modules/webpack-dev-server": {
+ "version": "4.11.1",
+ "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.11.1.tgz",
+ "integrity": "sha512-lILVz9tAUy1zGFwieuaQtYiadImb5M3d+H+L1zDYalYoDl0cksAB1UNyuE5MMWJrG6zR1tXkCP2fitl7yoUJiw==",
+ "dev": true,
+ "dependencies": {
+ "@types/bonjour": "^3.5.9",
+ "@types/connect-history-api-fallback": "^1.3.5",
+ "@types/express": "^4.17.13",
+ "@types/serve-index": "^1.9.1",
+ "@types/serve-static": "^1.13.10",
+ "@types/sockjs": "^0.3.33",
+ "@types/ws": "^8.5.1",
+ "ansi-html-community": "^0.0.8",
+ "bonjour-service": "^1.0.11",
+ "chokidar": "^3.5.3",
+ "colorette": "^2.0.10",
+ "compression": "^1.7.4",
+ "connect-history-api-fallback": "^2.0.0",
+ "default-gateway": "^6.0.3",
+ "express": "^4.17.3",
+ "graceful-fs": "^4.2.6",
+ "html-entities": "^2.3.2",
+ "http-proxy-middleware": "^2.0.3",
+ "ipaddr.js": "^2.0.1",
+ "open": "^8.0.9",
+ "p-retry": "^4.5.0",
+ "rimraf": "^3.0.2",
+ "schema-utils": "^4.0.0",
+ "selfsigned": "^2.1.1",
+ "serve-index": "^1.9.1",
+ "sockjs": "^0.3.24",
+ "spdy": "^4.0.2",
+ "webpack-dev-middleware": "^5.3.1",
+ "ws": "^8.4.2"
+ },
+ "bin": {
+ "webpack-dev-server": "bin/webpack-dev-server.js"
+ },
+ "engines": {
+ "node": ">= 12.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "^4.37.0 || ^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "webpack-cli": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/webpack-merge": {
+ "version": "5.8.0",
+ "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz",
+ "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==",
+ "dev": true,
+ "dependencies": {
+ "clone-deep": "^4.0.1",
+ "wildcard": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "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,
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/webpack/node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "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"
+ }
+ },
+ "node_modules/webpack/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==",
+ "dev": true,
+ "peerDependencies": {
+ "ajv": "^6.9.1"
+ }
+ },
+ "node_modules/webpack/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/webpack/node_modules/schema-utils": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
+ "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==",
+ "dev": 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/websocket-driver": {
+ "version": "0.7.4",
+ "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
+ "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==",
+ "dev": true,
+ "dependencies": {
+ "http-parser-js": ">=0.5.1",
+ "safe-buffer": ">=5.1.0",
+ "websocket-extensions": ">=0.1.1"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/websocket-extensions": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz",
+ "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "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,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/wildcard": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz",
+ "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==",
+ "dev": true
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+ "dev": true
+ },
+ "node_modules/ws": {
+ "version": "8.7.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.7.0.tgz",
+ "integrity": "sha512-c2gsP0PRwcLFzUiA8Mkr37/MI7ilIlHQxaEAtd0uNMbVMoy8puJyafRlm0bV9MbGSabUPeLrRRaqIBcFcA2Pqg==",
+ "dev": true,
+ "engines": {
+ "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/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ }
+ },
+ "dependencies": {
+ "@dimforge/rapier2d": {
+ "version": "file:../builds/rapier2d",
+ "requires": {
+ "rimraf": "^3.0.2",
+ "typedoc": "^0.25.13",
+ "wasm-pack": "^0.12.1"
+ }
+ },
+ "@discoveryjs/json-ext": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
+ "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==",
+ "dev": true
+ },
+ "@jridgewell/gen-mapping": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz",
+ "integrity": "sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==",
+ "dev": true,
+ "requires": {
+ "@jridgewell/set-array": "^1.0.0",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ }
+ },
+ "@jridgewell/resolve-uri": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz",
+ "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==",
+ "dev": true
+ },
+ "@jridgewell/set-array": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.1.tgz",
+ "integrity": "sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==",
+ "dev": true
+ },
+ "@jridgewell/source-map": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz",
+ "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==",
+ "dev": true,
+ "requires": {
+ "@jridgewell/gen-mapping": "^0.3.0",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ }
+ },
+ "@jridgewell/sourcemap-codec": {
+ "version": "1.4.13",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz",
+ "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==",
+ "dev": true
+ },
+ "@jridgewell/trace-mapping": {
+ "version": "0.3.13",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz",
+ "integrity": "sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==",
+ "dev": true,
+ "requires": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
+ "@leichtgewicht/ip-codec": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz",
+ "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==",
+ "dev": true
+ },
+ "@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,
+ "requires": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ }
+ },
+ "@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true
+ },
+ "@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ }
+ },
+ "@pixi/accessibility": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/accessibility/-/accessibility-6.5.8.tgz",
+ "integrity": "sha512-3q1YaZeZKOoblgbxTQg2L0RAp9jtNtGcl/7kce+XelqxwIMS3p8411nwo90YO53XCqc/eQW2SoZ+hSXqcL0qOw==",
+ "requires": {}
+ },
+ "@pixi/app": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/app/-/app-6.5.8.tgz",
+ "integrity": "sha512-pDPkamtYDaPhscNxack+bHNqazCwrqw6cAotKyoz1mvLXeGhxqTntOcfgGLZR2fNbnY8EBmdduLvH7n2jI/LTg==",
+ "requires": {}
+ },
+ "@pixi/compressed-textures": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/compressed-textures/-/compressed-textures-6.5.8.tgz",
+ "integrity": "sha512-nW74kcvdEoe4a2U7Ekx4egqdH1tYKC2kCOZxKWYcUARqz26tS0ddwSRyIs05In6EChmXHXGy/MtShdueMH38TA==",
+ "requires": {}
+ },
+ "@pixi/constants": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/constants/-/constants-6.5.8.tgz",
+ "integrity": "sha512-yYRCebBPqajm1kn5f8QQTTvl7oDRDk1nppfO+JpqbrFXg0W7oqIMurec3KeG9RdZW5foOiXDoz1Gw+VtolYIEw=="
+ },
+ "@pixi/core": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/core/-/core-6.5.8.tgz",
+ "integrity": "sha512-Gconik7/PpFPMpCpOddXVIPx5C2StWKw7lQ4YX19yQ+cRRmecCea2cV0xTBtpEjjx0ilX7nBfIEuZ4zIlMmlbA==",
+ "requires": {
+ "@types/offscreencanvas": "^2019.6.4"
+ }
+ },
+ "@pixi/display": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/display/-/display-6.5.8.tgz",
+ "integrity": "sha512-2K8YOG8s0iF8x/k2Q0RTFmoMJ9biI6PXEh76nH3EqUFdpyrIIgrG5aOMnCkVDvOxlgVRrKG8Q3JBHlSievTmuw==",
+ "requires": {}
+ },
+ "@pixi/extensions": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/extensions/-/extensions-6.5.8.tgz",
+ "integrity": "sha512-6vEV801Vn/EkU/qjFiZ76OZWPq5KsBR2r+P5gfKv4YLnaDc3A+0IpUOJ7sLBAJqmr0iw68g6xV6MnuqVjNGjFg=="
+ },
+ "@pixi/extract": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/extract/-/extract-6.5.8.tgz",
+ "integrity": "sha512-qbuuD/iBA4J+TCBgrbMe8oDUFbCriyy9LTKEtQp+pghKD5MEMvJ3nO6Osumxqiqta2kYU6WldFLTldKyHEiQ7Q==",
+ "requires": {}
+ },
+ "@pixi/filter-alpha": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/filter-alpha/-/filter-alpha-6.5.8.tgz",
+ "integrity": "sha512-W4IkFTLTP84H+DS9XIdBGunAEpaXLrasDc4CQBeyp4c4hBlGlzriUZp30vkmqm7GPmFhzPe7aiJtNYgUpxKQBQ==",
+ "requires": {}
+ },
+ "@pixi/filter-blur": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/filter-blur/-/filter-blur-6.5.8.tgz",
+ "integrity": "sha512-1UOfVthFBnavzTBkR6R+1tWhOOymtWvcpuJILhxf3mryLj9eqYbQubAG0gV8Da6Ibsgk+v73ORnOJyWR3POFvw==",
+ "requires": {}
+ },
+ "@pixi/filter-color-matrix": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/filter-color-matrix/-/filter-color-matrix-6.5.8.tgz",
+ "integrity": "sha512-iix+a/KEi6HAwZwkUH3nkIzyLu0ln3HBuHEFLUUhug7xrQgQgGrTQZ32iWlfpJD/BZuKphIGfzlxMFfvyQmkVw==",
+ "requires": {}
+ },
+ "@pixi/filter-displacement": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/filter-displacement/-/filter-displacement-6.5.8.tgz",
+ "integrity": "sha512-qLRka5cQbeH6667A+ViYoemsXGGe2tOBt92vM91+slMt9OBGtR0ymlpGU7VxBggWUlu5PE10zYed/xw78uSpig==",
+ "requires": {}
+ },
+ "@pixi/filter-fxaa": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/filter-fxaa/-/filter-fxaa-6.5.8.tgz",
+ "integrity": "sha512-TxsBH2z2RMj0mqr13VPi18/EJ/Kn38J2u65HonJmhbvTaoK9HWMExTvl38Xjg0k7TlepwhoayxMhQ1uCw9xudQ==",
+ "requires": {}
+ },
+ "@pixi/filter-noise": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/filter-noise/-/filter-noise-6.5.8.tgz",
+ "integrity": "sha512-BZHKuzV5Mdn+EpC52lFYpd6jUcrL+YQHdq0v0yJfVtpW2ripseQxMGxxXr6Yxp2P4F3g2aY2JrfX2VztosmGLA==",
+ "requires": {}
+ },
+ "@pixi/graphics": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/graphics/-/graphics-6.5.8.tgz",
+ "integrity": "sha512-DUuUXHO4t5fg+n+srMkHX38QEH3WtS1IMXtovBGFJkkopG0Z0xjxSp5XvsPPw1J//4fzkHZI5OBrlN613p9+sg==",
+ "requires": {}
+ },
+ "@pixi/interaction": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/interaction/-/interaction-6.5.8.tgz",
+ "integrity": "sha512-uP247r0f47vo9WSpEnsUfeD1izxVGpjtg4iAyGT/02ezWse2vD1aEL8AbxFa65TL0IXOKsHEQudCVL+wjnbSKQ==",
+ "requires": {}
+ },
+ "@pixi/loaders": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/loaders/-/loaders-6.5.8.tgz",
+ "integrity": "sha512-mj11UPKsqWaTEPMpCnFugr6heKkQeNFuVSddSwE8crg19l46zcMhk3ucpQX15RDpAdDJjtl3OraevQCHHbNENw==",
+ "requires": {}
+ },
+ "@pixi/math": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/math/-/math-6.5.8.tgz",
+ "integrity": "sha512-9493KEH5ITnjOZvQZbaU22lD0kcg/XhNh+309KYfwFX787zA1BN/7is06oHEgHBDb2NemqioYi6sw1WnECgQig=="
+ },
+ "@pixi/mesh": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/mesh/-/mesh-6.5.8.tgz",
+ "integrity": "sha512-iZZGkh8QBhnfMEgpJsuwemFZZVatodckCgj7N8t1hyHEf0aOWEA6wp5N0Osa3mhltokl7BGnZZLxaR8NtjaiEQ==",
+ "requires": {}
+ },
+ "@pixi/mesh-extras": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/mesh-extras/-/mesh-extras-6.5.8.tgz",
+ "integrity": "sha512-eU2I53yZUFxKbTYZvyRfUcdina3WOl87fyqYwAoaHosU9VgbFl16YADKTGV+NflNp6RCTwU/UIPZ1T19W/iysw==",
+ "requires": {}
+ },
+ "@pixi/mixin-cache-as-bitmap": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/mixin-cache-as-bitmap/-/mixin-cache-as-bitmap-6.5.8.tgz",
+ "integrity": "sha512-5TTv4w8v7guI6z3gKz5ppUCbNMRw+8RRNru/aq65qUl6kcUaJiYwQdBFJ/vJwpI9ePEScWrCuLVEc8QtX6xjNw==",
+ "requires": {}
+ },
+ "@pixi/mixin-get-child-by-name": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/mixin-get-child-by-name/-/mixin-get-child-by-name-6.5.8.tgz",
+ "integrity": "sha512-b15HTdHpW4ErDBpf7wm1vvWHrTv5kQzElXrwAPBCnLgvronfSL9mL7npOUkZOybUorCoEBq/7oNVjkimsQc5gw==",
+ "requires": {}
+ },
+ "@pixi/mixin-get-global-position": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/mixin-get-global-position/-/mixin-get-global-position-6.5.8.tgz",
+ "integrity": "sha512-Y5epEW5mRrgpDOHvfc92t0PaBgboBKXR4n/AzOOFt0h9GRNTmVKYBpUQPp/HO+r1Bxq+XbaGm1CyfkjUUxnORA==",
+ "requires": {}
+ },
+ "@pixi/particle-container": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/particle-container/-/particle-container-6.5.8.tgz",
+ "integrity": "sha512-wc4j84PssPWmZLpOJTLLC7MftCULzkQMAfVlwOERhNTZ+6E1LIKw91wDWZe9LQ/20iarzQwQXo0a4uNlJlhnVQ==",
+ "requires": {}
+ },
+ "@pixi/polyfill": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/polyfill/-/polyfill-6.5.8.tgz",
+ "integrity": "sha512-z2klHelxTZExMyO4oiLdxJMGzzXnToEIDn7Dwfy3FY+98LbxSa2dVFCgzDsYeiiS8fSMsni2Ru7aZT/DFsRDcA==",
+ "requires": {
+ "object-assign": "^4.1.1",
+ "promise-polyfill": "^8.2.0"
+ }
+ },
+ "@pixi/prepare": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/prepare/-/prepare-6.5.8.tgz",
+ "integrity": "sha512-anrAcjX3r9ZzK/L6Fw7GhE1pCkjhSfBsxUTlVhuRKJPFC+A3BNpZCwy3GzyvHP4ocl8wvUMzuz5BB5l0AoBCFw==",
+ "requires": {}
+ },
+ "@pixi/runner": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/runner/-/runner-6.5.8.tgz",
+ "integrity": "sha512-/9KVgQjTKiBa1qHdNmhP9I+AHgC/Eu9QiKcc+oakLCJtpYi79lx+nDFrpLUamIi2c7lP0hDWVe0XqlQeYmSwag=="
+ },
+ "@pixi/settings": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/settings/-/settings-6.5.8.tgz",
+ "integrity": "sha512-gmnwHkg9+tlQRuFNOdimzl73Dup2fdEo/VYaF7spT+8womE4KWAvARCBMqY/10aAx1iYeYuo5av/RfqrePB5Hg==",
+ "requires": {}
+ },
+ "@pixi/sprite": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/sprite/-/sprite-6.5.8.tgz",
+ "integrity": "sha512-ywvbrNgjK+K93X9cvHtDCnsBtU7B9JD/3wg+1G6v1Ktrr2E1gwVIQK1NANBrjzt6cYGphz5EqGAW68d0rMBliw==",
+ "requires": {}
+ },
+ "@pixi/sprite-animated": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/sprite-animated/-/sprite-animated-6.5.8.tgz",
+ "integrity": "sha512-woPT2cF1BaC0PDWdDrqJ0+DYcyIeXzZLq6bVx2YYia3+jJao1Zjmz1ns5e7YMUTEG7DoVFfhO6CC81YimsMG5w==",
+ "requires": {}
+ },
+ "@pixi/sprite-tiling": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/sprite-tiling/-/sprite-tiling-6.5.8.tgz",
+ "integrity": "sha512-PG3tiWI6uUest/d7HAz4/3I8NjpYyeMUL2WDy86nMXCJ6bLdTs/s9Nq3DLckaUsyIMTGsVbj/BXjE8LP1WDTog==",
+ "requires": {}
+ },
+ "@pixi/spritesheet": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/spritesheet/-/spritesheet-6.5.8.tgz",
+ "integrity": "sha512-WiJd4fKpSitD3A+/u5q8IPoHXMFT8++bsluhuJvDwzo//s0PHb9qExlF2xos7zUmekmydEFMkDnrl4+lWn2cyg==",
+ "requires": {}
+ },
+ "@pixi/text": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/text/-/text-6.5.8.tgz",
+ "integrity": "sha512-7AZPj5+vWcUjK0QzQ3ehiEwEqywiWR8NhDmnnN5nRNHR9u5IOOnqCQtBTdDffYPN0uMgCi8MzUPwTJhGuyOeww==",
+ "requires": {}
+ },
+ "@pixi/text-bitmap": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/text-bitmap/-/text-bitmap-6.5.8.tgz",
+ "integrity": "sha512-6VxejDc0gOu5HFN06m6i94xBZHdZ728iao8q+hEOjavGR5i2Pv3xseuke1qY0iN4q6Z+wTkcmoK5BfEVi2ujdQ==",
+ "requires": {}
+ },
+ "@pixi/ticker": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/ticker/-/ticker-6.5.8.tgz",
+ "integrity": "sha512-7VKq5hfnRDSv6a16pATqZAmpQfEu4G171iUTloy3QZfbnPw0s3JervZSih1yJJD84GXEF4VzYB26pJ/x3arGjQ==",
+ "requires": {}
+ },
+ "@pixi/utils": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/@pixi/utils/-/utils-6.5.8.tgz",
+ "integrity": "sha512-zLnvmVQBWPDnwkfvrSpBBF2XpWSMt+kQAsX562eqjuME63ic9M6fK4u/IaA8csdlG2wtcjBvSYWrpWmPq0bWag==",
+ "requires": {
+ "@types/earcut": "^2.1.0",
+ "earcut": "^2.2.4",
+ "eventemitter3": "^3.1.0",
+ "url": "^0.11.0"
+ },
+ "dependencies": {
+ "eventemitter3": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz",
+ "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q=="
+ }
+ }
+ },
+ "@types/body-parser": {
+ "version": "1.19.2",
+ "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz",
+ "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==",
+ "dev": true,
+ "requires": {
+ "@types/connect": "*",
+ "@types/node": "*"
+ }
+ },
+ "@types/bonjour": {
+ "version": "3.5.10",
+ "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz",
+ "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "@types/connect": {
+ "version": "3.4.35",
+ "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz",
+ "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "@types/connect-history-api-fallback": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz",
+ "integrity": "sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==",
+ "dev": true,
+ "requires": {
+ "@types/express-serve-static-core": "*",
+ "@types/node": "*"
+ }
+ },
+ "@types/earcut": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@types/earcut/-/earcut-2.1.1.tgz",
+ "integrity": "sha512-w8oigUCDjElRHRRrMvn/spybSMyX8MTkKA5Dv+tS1IE/TgmNZPqUYtvYBXGY8cieSE66gm+szeK+bnbxC2xHTQ=="
+ },
+ "@types/eslint": {
+ "version": "8.4.2",
+ "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.2.tgz",
+ "integrity": "sha512-Z1nseZON+GEnFjJc04sv4NSALGjhFwy6K0HXt7qsn5ArfAKtb63dXNJHf+1YW6IpOIYRBGUbu3GwJdj8DGnCjA==",
+ "dev": true,
+ "requires": {
+ "@types/estree": "*",
+ "@types/json-schema": "*"
+ }
+ },
+ "@types/eslint-scope": {
+ "version": "3.7.3",
+ "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz",
+ "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==",
+ "dev": true,
+ "requires": {
+ "@types/eslint": "*",
+ "@types/estree": "*"
+ }
+ },
+ "@types/estree": {
+ "version": "0.0.51",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz",
+ "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==",
+ "dev": true
+ },
+ "@types/express": {
+ "version": "4.17.13",
+ "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz",
+ "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==",
+ "dev": true,
+ "requires": {
+ "@types/body-parser": "*",
+ "@types/express-serve-static-core": "^4.17.18",
+ "@types/qs": "*",
+ "@types/serve-static": "*"
+ }
+ },
+ "@types/express-serve-static-core": {
+ "version": "4.17.28",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz",
+ "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*",
+ "@types/qs": "*",
+ "@types/range-parser": "*"
+ }
+ },
+ "@types/http-proxy": {
+ "version": "1.17.9",
+ "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.9.tgz",
+ "integrity": "sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "@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
+ },
+ "@types/mime": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz",
+ "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==",
+ "dev": true
+ },
+ "@types/node": {
+ "version": "17.0.38",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.38.tgz",
+ "integrity": "sha512-5jY9RhV7c0Z4Jy09G+NIDTsCZ5G0L5n+Z+p+Y7t5VJHM30bgwzSjVtlcBxqAj+6L/swIlvtOSzr8rBk/aNyV2g==",
+ "dev": true
+ },
+ "@types/offscreencanvas": {
+ "version": "2019.7.0",
+ "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.0.tgz",
+ "integrity": "sha512-PGcyveRIpL1XIqK8eBsmRBt76eFgtzuPiSTyKHZxnGemp2yzGzWpjYKAfK3wIMiU7eH+851yEpiuP8JZerTmWg=="
+ },
+ "@types/qs": {
+ "version": "6.9.7",
+ "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
+ "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==",
+ "dev": true
+ },
+ "@types/range-parser": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz",
+ "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==",
+ "dev": true
+ },
+ "@types/retry": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz",
+ "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==",
+ "dev": true
+ },
+ "@types/seedrandom": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-3.0.2.tgz",
+ "integrity": "sha512-YPLqEOo0/X8JU3rdiq+RgUKtQhQtrppE766y7vMTu8dGML7TVtZNiiiaC/hhU9Zqw9UYopXxhuWWENclMVBwKQ==",
+ "dev": true
+ },
+ "@types/serve-index": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz",
+ "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==",
+ "dev": true,
+ "requires": {
+ "@types/express": "*"
+ }
+ },
+ "@types/serve-static": {
+ "version": "1.13.10",
+ "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz",
+ "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==",
+ "dev": true,
+ "requires": {
+ "@types/mime": "^1",
+ "@types/node": "*"
+ }
+ },
+ "@types/sockjs": {
+ "version": "0.3.33",
+ "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz",
+ "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "@types/stats.js": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.0.tgz",
+ "integrity": "sha512-9w+a7bR8PeB0dCT/HBULU2fMqf6BAzvKbxFboYhmDtDkKPiyXYbjoe2auwsXlEFI7CFNMF1dCv3dFH5Poy9R1w==",
+ "dev": true
+ },
+ "@types/ws": {
+ "version": "8.5.3",
+ "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz",
+ "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "@webassemblyjs/ast": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz",
+ "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/helper-numbers": "1.11.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.11.1"
+ }
+ },
+ "@webassemblyjs/floating-point-hex-parser": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz",
+ "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==",
+ "dev": true
+ },
+ "@webassemblyjs/helper-api-error": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz",
+ "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==",
+ "dev": true
+ },
+ "@webassemblyjs/helper-buffer": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz",
+ "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==",
+ "dev": true
+ },
+ "@webassemblyjs/helper-numbers": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz",
+ "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/floating-point-hex-parser": "1.11.1",
+ "@webassemblyjs/helper-api-error": "1.11.1",
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "@webassemblyjs/helper-wasm-bytecode": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz",
+ "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==",
+ "dev": true
+ },
+ "@webassemblyjs/helper-wasm-section": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz",
+ "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.11.1",
+ "@webassemblyjs/helper-buffer": "1.11.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
+ "@webassemblyjs/wasm-gen": "1.11.1"
+ }
+ },
+ "@webassemblyjs/ieee754": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz",
+ "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==",
+ "dev": true,
+ "requires": {
+ "@xtuc/ieee754": "^1.2.0"
+ }
+ },
+ "@webassemblyjs/leb128": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz",
+ "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==",
+ "dev": true,
+ "requires": {
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "@webassemblyjs/utf8": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz",
+ "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==",
+ "dev": true
+ },
+ "@webassemblyjs/wasm-edit": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz",
+ "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.11.1",
+ "@webassemblyjs/helper-buffer": "1.11.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
+ "@webassemblyjs/helper-wasm-section": "1.11.1",
+ "@webassemblyjs/wasm-gen": "1.11.1",
+ "@webassemblyjs/wasm-opt": "1.11.1",
+ "@webassemblyjs/wasm-parser": "1.11.1",
+ "@webassemblyjs/wast-printer": "1.11.1"
+ }
+ },
+ "@webassemblyjs/wasm-gen": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz",
+ "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.11.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
+ "@webassemblyjs/ieee754": "1.11.1",
+ "@webassemblyjs/leb128": "1.11.1",
+ "@webassemblyjs/utf8": "1.11.1"
+ }
+ },
+ "@webassemblyjs/wasm-opt": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz",
+ "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.11.1",
+ "@webassemblyjs/helper-buffer": "1.11.1",
+ "@webassemblyjs/wasm-gen": "1.11.1",
+ "@webassemblyjs/wasm-parser": "1.11.1"
+ }
+ },
+ "@webassemblyjs/wasm-parser": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz",
+ "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.11.1",
+ "@webassemblyjs/helper-api-error": "1.11.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.11.1",
+ "@webassemblyjs/ieee754": "1.11.1",
+ "@webassemblyjs/leb128": "1.11.1",
+ "@webassemblyjs/utf8": "1.11.1"
+ }
+ },
+ "@webassemblyjs/wast-printer": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz",
+ "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.11.1",
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "@webpack-cli/configtest": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz",
+ "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==",
+ "dev": true,
+ "requires": {}
+ },
+ "@webpack-cli/info": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.5.0.tgz",
+ "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==",
+ "dev": true,
+ "requires": {
+ "envinfo": "^7.7.3"
+ }
+ },
+ "@webpack-cli/serve": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz",
+ "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==",
+ "dev": true,
+ "requires": {}
+ },
+ "@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
+ },
+ "@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
+ },
+ "accepts": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
+ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+ "dev": true,
+ "requires": {
+ "mime-types": "~2.1.34",
+ "negotiator": "0.6.3"
+ }
+ },
+ "acorn": {
+ "version": "8.7.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz",
+ "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==",
+ "dev": true
+ },
+ "acorn-import-assertions": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz",
+ "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==",
+ "dev": true,
+ "requires": {}
+ },
+ "ajv": {
+ "version": "8.11.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
+ "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "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,
+ "requires": {
+ "ajv": "^8.0.0"
+ }
+ },
+ "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,
+ "requires": {
+ "fast-deep-equal": "^3.1.3"
+ }
+ },
+ "ansi-html-community": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz",
+ "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "anymatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
+ "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
+ "dev": true,
+ "requires": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ }
+ },
+ "array-flatten": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz",
+ "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==",
+ "dev": true
+ },
+ "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
+ },
+ "batch": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
+ "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==",
+ "dev": true
+ },
+ "binary-extensions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+ "dev": true
+ },
+ "body-parser": {
+ "version": "1.20.0",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz",
+ "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==",
+ "dev": true,
+ "requires": {
+ "bytes": "3.1.2",
+ "content-type": "~1.0.4",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "on-finished": "2.4.1",
+ "qs": "6.10.3",
+ "raw-body": "2.5.1",
+ "type-is": "~1.6.18",
+ "unpipe": "1.0.0"
+ },
+ "dependencies": {
+ "bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "dev": true
+ }
+ }
+ },
+ "bonjour-service": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.0.12.tgz",
+ "integrity": "sha512-pMmguXYCu63Ug37DluMKEHdxc+aaIf/ay4YbF8Gxtba+9d3u+rmEWy61VK3Z3hp8Rskok3BunHYnG0dUHAsblw==",
+ "dev": true,
+ "requires": {
+ "array-flatten": "^2.1.2",
+ "dns-equal": "^1.0.0",
+ "fast-deep-equal": "^3.1.3",
+ "multicast-dns": "^7.2.4"
+ }
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
+ "browserslist": {
+ "version": "4.20.3",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz",
+ "integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==",
+ "dev": true,
+ "requires": {
+ "caniuse-lite": "^1.0.30001332",
+ "electron-to-chromium": "^1.4.118",
+ "escalade": "^3.1.1",
+ "node-releases": "^2.0.3",
+ "picocolors": "^1.0.0"
+ }
+ },
+ "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
+ },
+ "bytes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
+ "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==",
+ "dev": true
+ },
+ "call-bind": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
+ "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.0.2"
+ }
+ },
+ "caniuse-lite": {
+ "version": "1.0.30001344",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001344.tgz",
+ "integrity": "sha512-0ZFjnlCaXNOAYcV7i+TtdKBp0L/3XEU2MF/x6Du1lrh+SRX4IfzIVL4HNJg5pB2PmFb8rszIGyOvsZnqqRoc2g==",
+ "dev": true
+ },
+ "chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "chokidar": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
+ "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+ "dev": true,
+ "requires": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "fsevents": "~2.3.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"
+ },
+ "dependencies": {
+ "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,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ }
+ }
+ },
+ "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==",
+ "dev": true
+ },
+ "clone-deep": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
+ "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
+ "dev": true,
+ "requires": {
+ "is-plain-object": "^2.0.4",
+ "kind-of": "^6.0.2",
+ "shallow-clone": "^3.0.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "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==",
+ "dev": true
+ },
+ "colorette": {
+ "version": "2.0.16",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz",
+ "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==",
+ "dev": true
+ },
+ "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
+ },
+ "compressible": {
+ "version": "2.0.18",
+ "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
+ "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==",
+ "dev": true,
+ "requires": {
+ "mime-db": ">= 1.43.0 < 2"
+ }
+ },
+ "compression": {
+ "version": "1.7.4",
+ "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz",
+ "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==",
+ "dev": true,
+ "requires": {
+ "accepts": "~1.3.5",
+ "bytes": "3.0.0",
+ "compressible": "~2.0.16",
+ "debug": "2.6.9",
+ "on-headers": "~1.0.2",
+ "safe-buffer": "5.1.2",
+ "vary": "~1.1.2"
+ },
+ "dependencies": {
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ }
+ }
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "connect-history-api-fallback": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz",
+ "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==",
+ "dev": true
+ },
+ "content-disposition": {
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
+ "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "5.2.1"
+ }
+ },
+ "content-type": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
+ "dev": true
+ },
+ "cookie": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
+ "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
+ "dev": true
+ },
+ "cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
+ "dev": true
+ },
+ "copy-webpack-plugin": {
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz",
+ "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==",
+ "dev": true,
+ "requires": {
+ "fast-glob": "^3.2.11",
+ "glob-parent": "^6.0.1",
+ "globby": "^13.1.1",
+ "normalize-path": "^3.0.0",
+ "schema-utils": "^4.0.0",
+ "serialize-javascript": "^6.0.0"
+ }
+ },
+ "core-util-is": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
+ "dev": true
+ },
+ "cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ }
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "default-gateway": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz",
+ "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==",
+ "dev": true,
+ "requires": {
+ "execa": "^5.0.0"
+ }
+ },
+ "define-lazy-prop": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
+ "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==",
+ "dev": true
+ },
+ "depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "dev": true
+ },
+ "destroy": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
+ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
+ "dev": true
+ },
+ "detect-node": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz",
+ "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==",
+ "dev": true
+ },
+ "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,
+ "requires": {
+ "path-type": "^4.0.0"
+ }
+ },
+ "dns-equal": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
+ "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==",
+ "dev": true
+ },
+ "dns-packet": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.3.1.tgz",
+ "integrity": "sha512-spBwIj0TK0Ey3666GwIdWVfUpLyubpU53BTCu8iPn4r4oXd9O14Hjg3EHw3ts2oed77/SeckunUYCyRlSngqHw==",
+ "dev": true,
+ "requires": {
+ "@leichtgewicht/ip-codec": "^2.0.1"
+ }
+ },
+ "earcut": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz",
+ "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ=="
+ },
+ "ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+ "dev": true
+ },
+ "electron-to-chromium": {
+ "version": "1.4.143",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.143.tgz",
+ "integrity": "sha512-2hIgvu0+pDfXIqmVmV5X6iwMjQ2KxDsWKwM+oI1fABEOy/Dqmll0QJRmIQ3rm+XaoUa/qKrmy5h7LSTFQ6Ldzg==",
+ "dev": true
+ },
+ "encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+ "dev": true
+ },
+ "enhanced-resolve": {
+ "version": "5.10.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz",
+ "integrity": "sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.2.4",
+ "tapable": "^2.2.0"
+ }
+ },
+ "envinfo": {
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz",
+ "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==",
+ "dev": true
+ },
+ "es-module-lexer": {
+ "version": "0.9.3",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz",
+ "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==",
+ "dev": true
+ },
+ "escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+ "dev": true
+ },
+ "escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+ "dev": true
+ },
+ "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,
+ "requires": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ }
+ },
+ "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,
+ "requires": {
+ "estraverse": "^5.2.0"
+ },
+ "dependencies": {
+ "estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true
+ }
+ }
+ },
+ "estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true
+ },
+ "etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+ "dev": true
+ },
+ "eventemitter3": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
+ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
+ "dev": true
+ },
+ "events": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+ "dev": true
+ },
+ "execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+ "dev": true,
+ "requires": {
+ "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"
+ }
+ },
+ "express": {
+ "version": "4.18.1",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz",
+ "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==",
+ "dev": true,
+ "requires": {
+ "accepts": "~1.3.8",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.20.0",
+ "content-disposition": "0.5.4",
+ "content-type": "~1.0.4",
+ "cookie": "0.5.0",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "1.2.0",
+ "fresh": "0.5.2",
+ "http-errors": "2.0.0",
+ "merge-descriptors": "1.0.1",
+ "methods": "~1.1.2",
+ "on-finished": "2.4.1",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "0.1.7",
+ "proxy-addr": "~2.0.7",
+ "qs": "6.10.3",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.2.1",
+ "send": "0.18.0",
+ "serve-static": "1.15.0",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "type-is": "~1.6.18",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ },
+ "dependencies": {
+ "array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
+ "dev": true
+ }
+ }
+ },
+ "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
+ },
+ "fast-glob": {
+ "version": "3.2.11",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
+ "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==",
+ "dev": true,
+ "requires": {
+ "@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"
+ },
+ "dependencies": {
+ "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,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ }
+ }
+ },
+ "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
+ },
+ "fastest-levenshtein": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz",
+ "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==",
+ "dev": true
+ },
+ "fastq": {
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
+ "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==",
+ "dev": true,
+ "requires": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "faye-websocket": {
+ "version": "0.11.4",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz",
+ "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==",
+ "dev": true,
+ "requires": {
+ "websocket-driver": ">=0.5.1"
+ }
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "finalhandler": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
+ "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "on-finished": "2.4.1",
+ "parseurl": "~1.3.3",
+ "statuses": "2.0.1",
+ "unpipe": "~1.0.0"
+ }
+ },
+ "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,
+ "requires": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ }
+ },
+ "follow-redirects": {
+ "version": "1.15.1",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz",
+ "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==",
+ "dev": true
+ },
+ "forwarded": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+ "dev": true
+ },
+ "fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
+ "dev": true
+ },
+ "fs-monkey": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz",
+ "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==",
+ "dev": true
+ },
+ "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
+ },
+ "fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
+ "optional": true
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "get-intrinsic": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
+ "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.1"
+ }
+ },
+ "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
+ },
+ "glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "requires": {
+ "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"
+ }
+ },
+ "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,
+ "requires": {
+ "is-glob": "^4.0.3"
+ }
+ },
+ "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
+ },
+ "globby": {
+ "version": "13.1.1",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.1.tgz",
+ "integrity": "sha512-XMzoDZbGZ37tufiv7g0N4F/zp3zkwdFtVbV3EHsVl1KQr4RPLfNoT068/97RPshz2J5xYNEjLKKBKaGHifBd3Q==",
+ "dev": true,
+ "requires": {
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.11",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^4.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "handle-thing": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz",
+ "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==",
+ "dev": true
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "dev": true
+ },
+ "hash-wasm": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/hash-wasm/-/hash-wasm-4.12.0.tgz",
+ "integrity": "sha512-+/2B2rYLb48I/evdOIhP+K/DD2ca2fgBjp6O+GBEnCDk2e4rpeXIK8GvIyRPjTezgmWn9gmKwkQjjx6BtqDHVQ=="
+ },
+ "hpack.js": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
+ "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "obuf": "^1.0.0",
+ "readable-stream": "^2.0.1",
+ "wbuf": "^1.1.0"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "2.3.7",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+ "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+ "dev": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ }
+ }
+ },
+ "html-entities": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz",
+ "integrity": "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==",
+ "dev": true
+ },
+ "http-deceiver": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
+ "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==",
+ "dev": true
+ },
+ "http-errors": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
+ "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
+ "dev": true,
+ "requires": {
+ "depd": "2.0.0",
+ "inherits": "2.0.4",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "toidentifier": "1.0.1"
+ }
+ },
+ "http-parser-js": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.6.tgz",
+ "integrity": "sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA==",
+ "dev": true
+ },
+ "http-proxy": {
+ "version": "1.18.1",
+ "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
+ "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
+ "dev": true,
+ "requires": {
+ "eventemitter3": "^4.0.0",
+ "follow-redirects": "^1.0.0",
+ "requires-port": "^1.0.0"
+ }
+ },
+ "http-proxy-middleware": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz",
+ "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==",
+ "dev": true,
+ "requires": {
+ "@types/http-proxy": "^1.17.8",
+ "http-proxy": "^1.18.1",
+ "is-glob": "^4.0.1",
+ "is-plain-obj": "^3.0.0",
+ "micromatch": "^4.0.2"
+ }
+ },
+ "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
+ },
+ "iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dev": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "ignore": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
+ "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
+ "dev": true
+ },
+ "import-local": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz",
+ "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==",
+ "dev": true,
+ "requires": {
+ "pkg-dir": "^4.2.0",
+ "resolve-cwd": "^3.0.0"
+ }
+ },
+ "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,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "interpret": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz",
+ "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==",
+ "dev": true
+ },
+ "ipaddr.js": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz",
+ "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==",
+ "dev": true
+ },
+ "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,
+ "requires": {
+ "binary-extensions": "^2.0.0"
+ }
+ },
+ "is-core-module": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz",
+ "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.3"
+ }
+ },
+ "is-docker": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
+ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
+ "dev": true
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true
+ },
+ "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,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "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
+ },
+ "is-plain-obj": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz",
+ "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "isobject": "^3.0.1"
+ }
+ },
+ "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
+ },
+ "is-wsl": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
+ "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+ "dev": true,
+ "requires": {
+ "is-docker": "^2.0.0"
+ }
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
+ "dev": true
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==",
+ "dev": true
+ },
+ "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,
+ "requires": {
+ "@types/node": "*",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "dependencies": {
+ "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,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
+ "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
+ },
+ "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
+ },
+ "kind-of": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+ "dev": true
+ },
+ "lil-gui": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/lil-gui/-/lil-gui-0.17.0.tgz",
+ "integrity": "sha512-MVBHmgY+uEbmJNApAaPbtvNh1RCAeMnKym82SBjtp5rODTYKWtM+MXHCifLe2H2Ti1HuBGBtK/5SyG4ShQ3pUQ=="
+ },
+ "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==",
+ "dev": true
+ },
+ "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,
+ "requires": {
+ "p-locate": "^4.1.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
+ "media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
+ "dev": true
+ },
+ "memfs": {
+ "version": "3.4.4",
+ "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.4.tgz",
+ "integrity": "sha512-W4gHNUE++1oSJVn8Y68jPXi+mkx3fXR5ITE/Ubz6EQ3xRpCN5k2CQ4AUR8094Z7211F876TyoBACGsIveqgiGA==",
+ "dev": true,
+ "requires": {
+ "fs-monkey": "1.0.3"
+ }
+ },
+ "merge-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+ "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==",
+ "dev": true
+ },
+ "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
+ },
+ "merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true
+ },
+ "methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
+ "dev": true
+ },
+ "micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dev": true,
+ "requires": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ }
+ },
+ "mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "dev": true
+ },
+ "mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "mime-db": "1.52.0"
+ }
+ },
+ "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
+ },
+ "minimalistic-assert": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
+ "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "dev": true
+ },
+ "multicast-dns": {
+ "version": "7.2.5",
+ "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz",
+ "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==",
+ "dev": true,
+ "requires": {
+ "dns-packet": "^5.2.2",
+ "thunky": "^1.0.2"
+ }
+ },
+ "negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "dev": true
+ },
+ "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
+ },
+ "node-forge": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
+ "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
+ "dev": true
+ },
+ "node-releases": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz",
+ "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==",
+ "dev": true
+ },
+ "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
+ },
+ "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,
+ "requires": {
+ "path-key": "^3.0.0"
+ }
+ },
+ "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=="
+ },
+ "object-inspect": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
+ "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==",
+ "dev": true
+ },
+ "obuf": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
+ "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==",
+ "dev": true
+ },
+ "on-finished": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+ "dev": true,
+ "requires": {
+ "ee-first": "1.1.1"
+ }
+ },
+ "on-headers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
+ "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
+ "dev": true
+ },
+ "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,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dev": true,
+ "requires": {
+ "mimic-fn": "^2.1.0"
+ }
+ },
+ "open": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz",
+ "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==",
+ "dev": true,
+ "requires": {
+ "define-lazy-prop": "^2.0.0",
+ "is-docker": "^2.1.1",
+ "is-wsl": "^2.2.0"
+ }
+ },
+ "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,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "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,
+ "requires": {
+ "p-limit": "^2.2.0"
+ }
+ },
+ "p-retry": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz",
+ "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==",
+ "dev": true,
+ "requires": {
+ "@types/retry": "0.12.0",
+ "retry": "^0.13.1"
+ }
+ },
+ "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
+ },
+ "parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "dev": true
+ },
+ "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
+ },
+ "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
+ },
+ "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
+ },
+ "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
+ },
+ "path-to-regexp": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+ "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==",
+ "dev": true
+ },
+ "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
+ },
+ "picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+ "dev": true
+ },
+ "picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true
+ },
+ "pixi-viewport": {
+ "version": "4.37.0",
+ "resolved": "https://registry.npmjs.org/pixi-viewport/-/pixi-viewport-4.37.0.tgz",
+ "integrity": "sha512-bF22o1WbWeQ3TTHnxh5MYPzjXiKAG2ezAV6rm1oaEbA66hZAAU6lCs7BgwmEBiZKgHNGko1bIJQUSe7cXWJVCw==",
+ "requires": {}
+ },
+ "pixi.js": {
+ "version": "6.5.8",
+ "resolved": "https://registry.npmjs.org/pixi.js/-/pixi.js-6.5.8.tgz",
+ "integrity": "sha512-TAovIMCvKiWlonyAEbStOSq2+GZliRgs+Pqlavffa/D0Rmvmb78bytWRxgonGx1qkg7G8W7eIbF55tFP4a5Krw==",
+ "requires": {
+ "@pixi/accessibility": "6.5.8",
+ "@pixi/app": "6.5.8",
+ "@pixi/compressed-textures": "6.5.8",
+ "@pixi/constants": "6.5.8",
+ "@pixi/core": "6.5.8",
+ "@pixi/display": "6.5.8",
+ "@pixi/extensions": "6.5.8",
+ "@pixi/extract": "6.5.8",
+ "@pixi/filter-alpha": "6.5.8",
+ "@pixi/filter-blur": "6.5.8",
+ "@pixi/filter-color-matrix": "6.5.8",
+ "@pixi/filter-displacement": "6.5.8",
+ "@pixi/filter-fxaa": "6.5.8",
+ "@pixi/filter-noise": "6.5.8",
+ "@pixi/graphics": "6.5.8",
+ "@pixi/interaction": "6.5.8",
+ "@pixi/loaders": "6.5.8",
+ "@pixi/math": "6.5.8",
+ "@pixi/mesh": "6.5.8",
+ "@pixi/mesh-extras": "6.5.8",
+ "@pixi/mixin-cache-as-bitmap": "6.5.8",
+ "@pixi/mixin-get-child-by-name": "6.5.8",
+ "@pixi/mixin-get-global-position": "6.5.8",
+ "@pixi/particle-container": "6.5.8",
+ "@pixi/polyfill": "6.5.8",
+ "@pixi/prepare": "6.5.8",
+ "@pixi/runner": "6.5.8",
+ "@pixi/settings": "6.5.8",
+ "@pixi/sprite": "6.5.8",
+ "@pixi/sprite-animated": "6.5.8",
+ "@pixi/sprite-tiling": "6.5.8",
+ "@pixi/spritesheet": "6.5.8",
+ "@pixi/text": "6.5.8",
+ "@pixi/text-bitmap": "6.5.8",
+ "@pixi/ticker": "6.5.8",
+ "@pixi/utils": "6.5.8"
+ }
+ },
+ "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,
+ "requires": {
+ "find-up": "^4.0.0"
+ }
+ },
+ "process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+ "dev": true
+ },
+ "promise-polyfill": {
+ "version": "8.2.3",
+ "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.2.3.tgz",
+ "integrity": "sha512-Og0+jCRQetV84U8wVjMNccfGCnMQ9mGs9Hv78QFe+pSDD3gWTpz0y+1QCuxy5d/vBFuZ3iwP2eycAkvqIMPmWg=="
+ },
+ "proxy-addr": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+ "dev": true,
+ "requires": {
+ "forwarded": "0.2.0",
+ "ipaddr.js": "1.9.1"
+ },
+ "dependencies": {
+ "ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+ "dev": true
+ }
+ }
+ },
+ "punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true
+ },
+ "qs": {
+ "version": "6.10.3",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
+ "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==",
+ "dev": true,
+ "requires": {
+ "side-channel": "^1.0.4"
+ }
+ },
+ "querystring": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
+ "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g=="
+ },
+ "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
+ },
+ "randombytes": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+ "dev": true
+ },
+ "raw-body": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
+ "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
+ "dev": true,
+ "requires": {
+ "bytes": "3.1.2",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ },
+ "dependencies": {
+ "bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "dev": true
+ }
+ }
+ },
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ },
+ "readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dev": true,
+ "requires": {
+ "picomatch": "^2.2.1"
+ }
+ },
+ "rechoir": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz",
+ "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==",
+ "dev": true,
+ "requires": {
+ "resolve": "^1.9.0"
+ }
+ },
+ "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
+ },
+ "requires-port": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
+ "dev": true
+ },
+ "resolve": {
+ "version": "1.22.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
+ "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==",
+ "dev": true,
+ "requires": {
+ "is-core-module": "^2.8.1",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ }
+ },
+ "resolve-cwd": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+ "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
+ "dev": true,
+ "requires": {
+ "resolve-from": "^5.0.0"
+ }
+ },
+ "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
+ },
+ "retry": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
+ "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==",
+ "dev": true
+ },
+ "reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "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,
+ "requires": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "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==",
+ "dev": true
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true
+ },
+ "schema-utils": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz",
+ "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==",
+ "dev": true,
+ "requires": {
+ "@types/json-schema": "^7.0.9",
+ "ajv": "^8.8.0",
+ "ajv-formats": "^2.1.1",
+ "ajv-keywords": "^5.0.0"
+ }
+ },
+ "seedrandom": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz",
+ "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg=="
+ },
+ "select-hose": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
+ "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=",
+ "dev": true
+ },
+ "selfsigned": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz",
+ "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==",
+ "dev": true,
+ "requires": {
+ "node-forge": "^1"
+ }
+ },
+ "semver": {
+ "version": "7.3.7",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+ "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
+ "send": {
+ "version": "0.18.0",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
+ "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "2.0.0",
+ "mime": "1.6.0",
+ "ms": "2.1.3",
+ "on-finished": "2.4.1",
+ "range-parser": "~1.2.1",
+ "statuses": "2.0.1"
+ },
+ "dependencies": {
+ "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
+ }
+ }
+ },
+ "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,
+ "requires": {
+ "randombytes": "^2.1.0"
+ }
+ },
+ "serve-index": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
+ "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=",
+ "dev": true,
+ "requires": {
+ "accepts": "~1.3.4",
+ "batch": "0.6.1",
+ "debug": "2.6.9",
+ "escape-html": "~1.0.3",
+ "http-errors": "~1.6.2",
+ "mime-types": "~2.1.17",
+ "parseurl": "~1.3.2"
+ },
+ "dependencies": {
+ "depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
+ "dev": true
+ },
+ "http-errors": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
+ "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==",
+ "dev": true,
+ "requires": {
+ "depd": "~1.1.2",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.1.0",
+ "statuses": ">= 1.4.0 < 2"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==",
+ "dev": true
+ },
+ "setprototypeof": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
+ "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
+ "dev": true
+ },
+ "statuses": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
+ "dev": true
+ }
+ }
+ },
+ "serve-static": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
+ "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
+ "dev": true,
+ "requires": {
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "0.18.0"
+ }
+ },
+ "setprototypeof": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+ "dev": true
+ },
+ "shallow-clone": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
+ "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.2"
+ }
+ },
+ "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,
+ "requires": {
+ "shebang-regex": "^3.0.0"
+ }
+ },
+ "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
+ },
+ "side-channel": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
+ "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.0",
+ "get-intrinsic": "^1.0.2",
+ "object-inspect": "^1.9.0"
+ }
+ },
+ "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
+ },
+ "slash": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz",
+ "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==",
+ "dev": true
+ },
+ "sockjs": {
+ "version": "0.3.24",
+ "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz",
+ "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==",
+ "dev": true,
+ "requires": {
+ "faye-websocket": "^0.11.3",
+ "uuid": "^8.3.2",
+ "websocket-driver": "^0.7.4"
+ }
+ },
+ "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
+ },
+ "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,
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "spdy": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz",
+ "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==",
+ "dev": true,
+ "requires": {
+ "debug": "^4.1.0",
+ "handle-thing": "^2.0.0",
+ "http-deceiver": "^1.2.7",
+ "select-hose": "^2.0.0",
+ "spdy-transport": "^3.0.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "spdy-transport": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz",
+ "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==",
+ "dev": true,
+ "requires": {
+ "debug": "^4.1.0",
+ "detect-node": "^2.0.4",
+ "hpack.js": "^2.1.6",
+ "obuf": "^1.1.2",
+ "readable-stream": "^3.0.6",
+ "wbuf": "^1.7.3"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "stats.js": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/stats.js/-/stats.js-0.17.0.tgz",
+ "integrity": "sha1-scPcRtlEmLV4t/05hbgaznExzH0="
+ },
+ "statuses": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
+ "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "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
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ },
+ "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
+ },
+ "tapable": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
+ "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
+ "dev": true
+ },
+ "terser": {
+ "version": "5.14.0",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.0.tgz",
+ "integrity": "sha512-JC6qfIEkPBd9j1SMO3Pfn+A6w2kQV54tv+ABQLgZr7dA3k/DL/OBoYSWxzVpZev3J+bUHXfr55L8Mox7AaNo6g==",
+ "dev": true,
+ "requires": {
+ "@jridgewell/source-map": "^0.3.2",
+ "acorn": "^8.5.0",
+ "commander": "^2.20.0",
+ "source-map-support": "~0.5.20"
+ }
+ },
+ "terser-webpack-plugin": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz",
+ "integrity": "sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g==",
+ "dev": true,
+ "requires": {
+ "jest-worker": "^27.4.5",
+ "schema-utils": "^3.1.1",
+ "serialize-javascript": "^6.0.0",
+ "source-map": "^0.6.1",
+ "terser": "^5.7.2"
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ajv-keywords": {
+ "version": "3.5.2",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
+ "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
+ "dev": true,
+ "requires": {}
+ },
+ "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
+ },
+ "schema-utils": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
+ "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==",
+ "dev": true,
+ "requires": {
+ "@types/json-schema": "^7.0.8",
+ "ajv": "^6.12.5",
+ "ajv-keywords": "^3.5.2"
+ }
+ }
+ }
+ },
+ "thunky": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz",
+ "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==",
+ "dev": true
+ },
+ "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,
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ },
+ "toidentifier": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+ "dev": true
+ },
+ "ts-loader": {
+ "version": "9.4.1",
+ "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.4.1.tgz",
+ "integrity": "sha512-384TYAqGs70rn9F0VBnh6BPTfhga7yFNdC5gXbQpDrBj9/KsT4iRkGqKXhziofHOlE2j6YEaiTYVGKKvPhGWvw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^4.1.0",
+ "enhanced-resolve": "^5.0.0",
+ "micromatch": "^4.0.0",
+ "semver": "^7.3.4"
+ }
+ },
+ "type-is": {
+ "version": "1.6.18",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "dev": true,
+ "requires": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ }
+ },
+ "typescript": {
+ "version": "4.8.4",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz",
+ "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==",
+ "dev": true
+ },
+ "unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
+ "dev": true
+ },
+ "uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "url": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
+ "integrity": "sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==",
+ "requires": {
+ "punycode": "1.3.2",
+ "querystring": "0.2.0"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
+ "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw=="
+ }
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+ "dev": true
+ },
+ "utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
+ "dev": true
+ },
+ "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
+ },
+ "vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
+ "dev": true
+ },
+ "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,
+ "requires": {
+ "glob-to-regexp": "^0.4.1",
+ "graceful-fs": "^4.1.2"
+ }
+ },
+ "wbuf": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz",
+ "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==",
+ "dev": true,
+ "requires": {
+ "minimalistic-assert": "^1.0.0"
+ }
+ },
+ "webpack": {
+ "version": "5.74.0",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz",
+ "integrity": "sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==",
+ "dev": true,
+ "requires": {
+ "@types/eslint-scope": "^3.7.3",
+ "@types/estree": "^0.0.51",
+ "@webassemblyjs/ast": "1.11.1",
+ "@webassemblyjs/wasm-edit": "1.11.1",
+ "@webassemblyjs/wasm-parser": "1.11.1",
+ "acorn": "^8.7.1",
+ "acorn-import-assertions": "^1.7.6",
+ "browserslist": "^4.14.5",
+ "chrome-trace-event": "^1.0.2",
+ "enhanced-resolve": "^5.10.0",
+ "es-module-lexer": "^0.9.0",
+ "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.0",
+ "tapable": "^2.1.1",
+ "terser-webpack-plugin": "^5.1.3",
+ "watchpack": "^2.4.0",
+ "webpack-sources": "^3.2.3"
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ajv-keywords": {
+ "version": "3.5.2",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
+ "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
+ "dev": true,
+ "requires": {}
+ },
+ "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
+ },
+ "schema-utils": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
+ "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==",
+ "dev": true,
+ "requires": {
+ "@types/json-schema": "^7.0.8",
+ "ajv": "^6.12.5",
+ "ajv-keywords": "^3.5.2"
+ }
+ }
+ }
+ },
+ "webpack-cli": {
+ "version": "4.10.0",
+ "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz",
+ "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==",
+ "dev": true,
+ "requires": {
+ "@discoveryjs/json-ext": "^0.5.0",
+ "@webpack-cli/configtest": "^1.2.0",
+ "@webpack-cli/info": "^1.5.0",
+ "@webpack-cli/serve": "^1.7.0",
+ "colorette": "^2.0.14",
+ "commander": "^7.0.0",
+ "cross-spawn": "^7.0.3",
+ "fastest-levenshtein": "^1.0.12",
+ "import-local": "^3.0.2",
+ "interpret": "^2.2.0",
+ "rechoir": "^0.7.0",
+ "webpack-merge": "^5.7.3"
+ },
+ "dependencies": {
+ "commander": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
+ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
+ "dev": true
+ }
+ }
+ },
+ "webpack-dev-middleware": {
+ "version": "5.3.3",
+ "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz",
+ "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==",
+ "dev": true,
+ "requires": {
+ "colorette": "^2.0.10",
+ "memfs": "^3.4.3",
+ "mime-types": "^2.1.31",
+ "range-parser": "^1.2.1",
+ "schema-utils": "^4.0.0"
+ }
+ },
+ "webpack-dev-server": {
+ "version": "4.11.1",
+ "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.11.1.tgz",
+ "integrity": "sha512-lILVz9tAUy1zGFwieuaQtYiadImb5M3d+H+L1zDYalYoDl0cksAB1UNyuE5MMWJrG6zR1tXkCP2fitl7yoUJiw==",
+ "dev": true,
+ "requires": {
+ "@types/bonjour": "^3.5.9",
+ "@types/connect-history-api-fallback": "^1.3.5",
+ "@types/express": "^4.17.13",
+ "@types/serve-index": "^1.9.1",
+ "@types/serve-static": "^1.13.10",
+ "@types/sockjs": "^0.3.33",
+ "@types/ws": "^8.5.1",
+ "ansi-html-community": "^0.0.8",
+ "bonjour-service": "^1.0.11",
+ "chokidar": "^3.5.3",
+ "colorette": "^2.0.10",
+ "compression": "^1.7.4",
+ "connect-history-api-fallback": "^2.0.0",
+ "default-gateway": "^6.0.3",
+ "express": "^4.17.3",
+ "graceful-fs": "^4.2.6",
+ "html-entities": "^2.3.2",
+ "http-proxy-middleware": "^2.0.3",
+ "ipaddr.js": "^2.0.1",
+ "open": "^8.0.9",
+ "p-retry": "^4.5.0",
+ "rimraf": "^3.0.2",
+ "schema-utils": "^4.0.0",
+ "selfsigned": "^2.1.1",
+ "serve-index": "^1.9.1",
+ "sockjs": "^0.3.24",
+ "spdy": "^4.0.2",
+ "webpack-dev-middleware": "^5.3.1",
+ "ws": "^8.4.2"
+ }
+ },
+ "webpack-merge": {
+ "version": "5.8.0",
+ "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz",
+ "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==",
+ "dev": true,
+ "requires": {
+ "clone-deep": "^4.0.1",
+ "wildcard": "^2.0.0"
+ }
+ },
+ "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
+ },
+ "websocket-driver": {
+ "version": "0.7.4",
+ "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
+ "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==",
+ "dev": true,
+ "requires": {
+ "http-parser-js": ">=0.5.1",
+ "safe-buffer": ">=5.1.0",
+ "websocket-extensions": ">=0.1.1"
+ }
+ },
+ "websocket-extensions": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz",
+ "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==",
+ "dev": true
+ },
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "wildcard": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz",
+ "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==",
+ "dev": true
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+ "dev": true
+ },
+ "ws": {
+ "version": "8.7.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.7.0.tgz",
+ "integrity": "sha512-c2gsP0PRwcLFzUiA8Mkr37/MI7ilIlHQxaEAtd0uNMbVMoy8puJyafRlm0bV9MbGSabUPeLrRRaqIBcFcA2Pqg==",
+ "dev": true,
+ "requires": {}
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ }
+ }
+}
diff --git a/typescript/testbed2d/package.json b/typescript/testbed2d/package.json
new file mode 100644
index 000000000..9152daa0e
--- /dev/null
+++ b/typescript/testbed2d/package.json
@@ -0,0 +1,32 @@
+{
+ "author": "sebcrozet ",
+ "name": "rapier-testbed2d",
+ "version": "0.1.0",
+ "description": "JavaScript testbed for rapier.",
+ "license": "Apache-2.0",
+ "main": "dist/rapier-testbed2d.js",
+ "scripts": {
+ "build": "rimraf dist pkg && webpack",
+ "start": "rimraf dist pkg && webpack serve --open --node-env development"
+ },
+ "dependencies": {
+ "@dimforge/rapier2d": "file:../builds/rapier2d",
+ "hash-wasm": "^4.12.0",
+ "lil-gui": "^0.17.0",
+ "pixi-viewport": "^4.37.0",
+ "pixi.js": "^6.3.2",
+ "seedrandom": "^3.0.5",
+ "stats.js": "^0.17.0"
+ },
+ "devDependencies": {
+ "@types/seedrandom": "^3.0.2",
+ "@types/stats.js": "^0.17.0",
+ "copy-webpack-plugin": "^11.0.0",
+ "rimraf": "^3.0.2",
+ "ts-loader": "^9.4.1",
+ "typescript": "^4.8.4",
+ "webpack": "^5.74.0",
+ "webpack-cli": "^4.10.0",
+ "webpack-dev-server": "^4.11.1"
+ }
+}
diff --git a/typescript/testbed2d/publish.sh b/typescript/testbed2d/publish.sh
new file mode 100755
index 000000000..087c63bec
--- /dev/null
+++ b/typescript/testbed2d/publish.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+npm run build
+rsync -av dist/ crozet@ssh.cluster003.hosting.ovh.net:/home/crozet/rapier/demos2d
+# rsync -av dist/Box2D_v2.3.1_min.wasm.wasm crozet@ssh.cluster003.hosting.ovh.net:/home/crozet/rapier/Box2D_v2.3.1_min.wasm.wasm
diff --git a/typescript/testbed2d/src/Graphics.ts b/typescript/testbed2d/src/Graphics.ts
new file mode 100644
index 000000000..4f9448f8d
--- /dev/null
+++ b/typescript/testbed2d/src/Graphics.ts
@@ -0,0 +1,269 @@
+import * as PIXI from "pixi.js";
+import {Viewport} from "pixi-viewport";
+import type * as RAPIER from "@dimforge/rapier2d";
+
+type RAPIER_API = typeof import("@dimforge/rapier2d");
+
+const BOX_INSTANCE_INDEX = 0;
+const BALL_INSTANCE_INDEX = 1;
+
+var kk = 0;
+
+export class Graphics {
+ coll2gfx: Map;
+ colorIndex: number;
+ colorPalette: Array;
+ renderer: PIXI.Renderer;
+ scene: PIXI.Container;
+ viewport: Viewport;
+ instanceGroups: Array>;
+ lines: PIXI.Graphics;
+
+ constructor() {
+ // High pixel Ratio make the rendering extremely slow, so we cap it.
+ // const pixelRatio = window.devicePixelRatio ? Math.min(window.devicePixelRatio, 1.5) : 1;
+
+ this.coll2gfx = new Map();
+ this.colorIndex = 0;
+ this.colorPalette = [0xf3d9b1, 0x98c1d9, 0x053c5e, 0x1f7a8c];
+ this.renderer = new PIXI.Renderer({
+ backgroundColor: 0x292929,
+ antialias: true,
+ // resolution: pixelRatio,
+ width: window.innerWidth,
+ height: window.innerHeight,
+ });
+
+ this.scene = new PIXI.Container();
+ document.body.appendChild(this.renderer.view);
+
+ this.viewport = new Viewport({
+ screenWidth: window.innerWidth,
+ screenHeight: window.innerHeight,
+ worldWidth: 1000,
+ worldHeight: 1000,
+ interaction: this.renderer.plugins.interaction,
+ });
+
+ this.scene.addChild(this.viewport);
+ this.viewport.drag().pinch().wheel().decelerate();
+
+ let me = this;
+
+ function onWindowResize() {
+ me.renderer.resize(window.innerWidth, window.innerHeight);
+ }
+
+ function onContextMenu(event: UIEvent) {
+ event.preventDefault();
+ }
+
+ document.oncontextmenu = onContextMenu;
+ document.body.oncontextmenu = onContextMenu;
+
+ window.addEventListener("resize", onWindowResize, false);
+
+ this.initInstances();
+ }
+
+ initInstances() {
+ this.instanceGroups = [];
+ this.instanceGroups.push(
+ this.colorPalette.map((color) => {
+ let graphics = new PIXI.Graphics();
+ graphics.beginFill(color);
+ graphics.drawRect(-1.0, 1.0, 2.0, -2.0);
+ graphics.endFill();
+ return graphics;
+ }),
+ );
+
+ this.instanceGroups.push(
+ this.colorPalette.map((color) => {
+ let graphics = new PIXI.Graphics();
+ graphics.beginFill(color);
+ graphics.drawCircle(0.0, 0.0, 1.0);
+ graphics.endFill();
+ return graphics;
+ }),
+ );
+ }
+
+ render(world: RAPIER.World, debugRender: Boolean) {
+ kk += 1;
+
+ if (!this.lines) {
+ this.lines = new PIXI.Graphics();
+ this.viewport.addChild(this.lines);
+ }
+
+ if (debugRender) {
+ let buffers = world.debugRender();
+ let vtx = buffers.vertices;
+ let cls = buffers.colors;
+
+ this.lines.clear();
+
+ for (let i = 0; i < vtx.length / 4; i += 1) {
+ let color = PIXI.utils.rgb2hex([
+ cls[i * 8],
+ cls[i * 8 + 1],
+ cls[i * 8 + 2],
+ ]);
+ this.lines.lineStyle(1.0, color, cls[i * 8 + 3], 0.5, true);
+ this.lines.moveTo(vtx[i * 4], -vtx[i * 4 + 1]);
+ this.lines.lineTo(vtx[i * 4 + 2], -vtx[i * 4 + 3]);
+ }
+ } else {
+ this.lines.clear();
+ }
+
+ this.updatePositions(world);
+ this.renderer.render(this.scene);
+ }
+
+ lookAt(pos: {zoom: number; target: {x: number; y: number}}) {
+ this.viewport.setZoom(pos.zoom);
+ this.viewport.moveCenter(pos.target.x, pos.target.y);
+ }
+
+ updatePositions(world: RAPIER.World) {
+ world.forEachCollider((elt) => {
+ let gfx = this.coll2gfx.get(elt.handle);
+ let translation = elt.translation();
+ let rotation = elt.rotation();
+
+ if (!!gfx) {
+ gfx.position.x = translation.x;
+ gfx.position.y = -translation.y;
+ gfx.rotation = -rotation;
+ }
+ });
+ }
+
+ reset() {
+ this.coll2gfx.forEach((gfx) => {
+ this.viewport.removeChild(gfx);
+ gfx.destroy();
+ });
+ this.coll2gfx = new Map();
+ this.colorIndex = 0;
+ }
+
+ addCollider(
+ RAPIER: RAPIER_API,
+ world: RAPIER.World,
+ collider: RAPIER.Collider,
+ ) {
+ let i;
+ let parent = collider.parent();
+ let instance;
+ let graphics;
+ let vertices;
+ let instanceId = parent.isFixed() ? 0 : this.colorIndex + 1;
+
+ switch (collider.shapeType()) {
+ case RAPIER.ShapeType.Cuboid:
+ let hext = collider.halfExtents();
+ instance = this.instanceGroups[BOX_INSTANCE_INDEX][instanceId];
+ graphics = instance.clone();
+ graphics.scale.x = hext.x;
+ graphics.scale.y = hext.y;
+ this.viewport.addChild(graphics);
+ break;
+ case RAPIER.ShapeType.Ball:
+ let rad = collider.radius();
+ instance = this.instanceGroups[BALL_INSTANCE_INDEX][instanceId];
+ graphics = instance.clone();
+ graphics.scale.x = rad;
+ graphics.scale.y = rad;
+ this.viewport.addChild(graphics);
+ break;
+ case RAPIER.ShapeType.Polyline:
+ vertices = Array.from(collider.vertices());
+ graphics = new PIXI.Graphics();
+ graphics
+ .lineStyle(0.2, this.colorPalette[instanceId])
+ .moveTo(vertices[0], -vertices[1]);
+
+ for (i = 2; i < vertices.length; i += 2) {
+ graphics.lineTo(vertices[i], -vertices[i + 1]);
+ }
+
+ this.viewport.addChild(graphics);
+ break;
+ case RAPIER.ShapeType.HeightField:
+ let heights = Array.from(collider.heightfieldHeights());
+ let scale = collider.heightfieldScale();
+ let step = scale.x / (heights.length - 1);
+
+ graphics = new PIXI.Graphics();
+ graphics
+ .lineStyle(0.2, this.colorPalette[instanceId])
+ .moveTo(-scale.x / 2.0, -heights[0] * scale.y);
+
+ for (i = 1; i < heights.length; i += 1) {
+ graphics.lineTo(
+ -scale.x / 2.0 + i * step,
+ -heights[i] * scale.y,
+ );
+ }
+
+ this.viewport.addChild(graphics);
+ break;
+ case RAPIER.ShapeType.ConvexPolygon:
+ vertices = Array.from(collider.vertices());
+ graphics = new PIXI.Graphics();
+ graphics.beginFill(this.colorPalette[instanceId], 1.0);
+ graphics.moveTo(vertices[0], -vertices[1]);
+
+ for (i = 2; i < vertices.length; i += 2) {
+ graphics.lineTo(vertices[i], -vertices[i + 1]);
+ }
+
+ this.viewport.addChild(graphics);
+ break;
+ case RAPIER.ShapeType.Voxels:
+ graphics = new PIXI.Graphics();
+ graphics.beginFill(this.colorPalette[instanceId], 1.0);
+ collider.clearShapeCache();
+ let shape = collider.shape as RAPIER.Voxels;
+ let gridCoords = shape.data;
+ let sz = shape.voxelSize;
+
+ for (i = 0; i < gridCoords.length; i += 2) {
+ let minx = gridCoords[i] * sz.x;
+ let miny = gridCoords[i + 1] * sz.y;
+ let maxx = minx + sz.x;
+ let maxy = miny + sz.y;
+
+ graphics.moveTo(minx, -miny);
+ graphics.lineTo(maxx, -miny);
+ graphics.lineTo(maxx, -maxy);
+ graphics.lineTo(minx, -maxy);
+ }
+
+ this.viewport.addChild(graphics);
+ break;
+ default:
+ console.log("Unknown shape to render: ", collider.shapeType());
+ return;
+ }
+
+ let t = collider.translation();
+ let r = collider.rotation();
+ // dummy.position.set(t.x, t.y, t.z);
+ // dummy.quaternion.set(r.x, r.y, r.z, r.w);
+ // dummy.scale.set(instanceDesc.scale.x, instanceDesc.scale.y, instanceDesc.scale.z);
+ // dummy.updateMatrix();
+ // instance.setMatrixAt(instanceDesc.elementId, dummy.matrix);
+ // instance.instanceMatrix.needsUpdate = true;
+ graphics.position.x = t.x;
+ graphics.position.y = -t.y;
+ graphics.rotation = r;
+
+ this.coll2gfx.set(collider.handle, graphics);
+ this.colorIndex =
+ (this.colorIndex + 1) % (this.colorPalette.length - 1);
+ }
+}
diff --git a/typescript/testbed2d/src/Gui.ts b/typescript/testbed2d/src/Gui.ts
new file mode 100644
index 000000000..a410607e3
--- /dev/null
+++ b/typescript/testbed2d/src/Gui.ts
@@ -0,0 +1,113 @@
+import GUI from "lil-gui";
+import * as Stats from "stats.js";
+import type {Testbed} from "./Testbed";
+
+export interface DebugInfos {
+ token: number;
+ stepId: number;
+ worldHash: string;
+ worldHashTime: number;
+ snapshotTime: number;
+}
+
+export class Gui {
+ stats: Stats;
+ rapierVersion: string;
+ maxTimePanelValue: number;
+ stepTimePanel: Stats.Panel;
+ gui: GUI;
+ debugText: HTMLDivElement;
+
+ constructor(testbed: Testbed, simulationParameters: Testbed["parameters"]) {
+ // Timings
+ this.stats = new Stats();
+ this.rapierVersion = testbed.RAPIER.version();
+ this.maxTimePanelValue = 16.0;
+ this.stepTimePanel = this.stats.addPanel(
+ new Stats.Panel("ms (step)", "#ff8", "#221"),
+ );
+ this.stats.showPanel(this.stats.dom.children.length - 1);
+ document.body.appendChild(this.stats.dom);
+
+ var backends = simulationParameters.backends;
+ var demos = Array.from(simulationParameters.builders.keys());
+ var me = this;
+
+ // For configuring simulation parameters.
+ this.gui = new GUI({
+ title: "Rapier JS demos",
+ });
+ var currDemo = this.gui
+ .add(simulationParameters, "demo", demos)
+ .onChange((demo: string) => {
+ testbed.switchToDemo(demo);
+ });
+ this.gui
+ .add(simulationParameters, "numSolverIters", 0, 20)
+ .step(1)
+ .listen();
+ this.gui
+ .add(simulationParameters, "debugInfos")
+ .listen()
+ .onChange((value: boolean) => {
+ me.debugText.style.visibility = value ? "visible" : "hidden";
+ });
+ this.gui.add(simulationParameters, "debugRender").listen();
+ this.gui.add(simulationParameters, "running").listen();
+ this.gui.add(simulationParameters, "step");
+ simulationParameters.step = () => {
+ simulationParameters.stepping = true;
+ };
+ this.gui.add(simulationParameters, "takeSnapshot");
+ simulationParameters.takeSnapshot = () => {
+ testbed.takeSnapshot();
+ };
+ this.gui.add(simulationParameters, "restoreSnapshot");
+ simulationParameters.restoreSnapshot = () => {
+ testbed.restoreSnapshot();
+ };
+ this.gui.add(simulationParameters, "restart");
+ simulationParameters.restart = () => {
+ testbed.switchToDemo(currDemo.getValue());
+ };
+
+ /*
+ * Block of text for debug infos.
+ */
+ this.debugText = document.createElement("div");
+ this.debugText.style.position = "absolute";
+ this.debugText.innerHTML = "";
+ this.debugText.style.top = 50 + "px";
+ this.debugText.style.visibility = "visible";
+ this.debugText.style.color = "#fff";
+ document.body.appendChild(this.debugText);
+ }
+
+ setDebugInfos(infos: DebugInfos) {
+ let text = "Version " + this.rapierVersion;
+ text += "
[Step " + infos.stepId + "]";
+
+ if (infos.worldHash) {
+ text +=
+ "
World hash (xxHash128): " + infos.worldHash.toString();
+ text +=
+ "
World hash time (xxHash128): " +
+ infos.worldHashTime +
+ "ms";
+ text += "
Snapshot time: " + infos.snapshotTime + "ms";
+ }
+ this.debugText.innerHTML = text;
+ }
+
+ setTiming(timing: number) {
+ if (!!timing) {
+ this.maxTimePanelValue = Math.max(this.maxTimePanelValue, timing);
+ this.stepTimePanel.update(timing, this.maxTimePanelValue);
+ }
+ }
+
+ resetTiming() {
+ this.maxTimePanelValue = 1.0;
+ this.stepTimePanel.update(0.0, 16.0);
+ }
+}
diff --git a/typescript/testbed2d/src/Testbed.ts b/typescript/testbed2d/src/Testbed.ts
new file mode 100644
index 000000000..61279ab2a
--- /dev/null
+++ b/typescript/testbed2d/src/Testbed.ts
@@ -0,0 +1,189 @@
+import {Graphics} from "./Graphics";
+import {Gui} from "./Gui";
+import type {DebugInfos} from "./Gui";
+import {xxhash128} from "hash-wasm";
+import type * as RAPIER from "@dimforge/rapier2d";
+
+type RAPIER_API = typeof import("@dimforge/rapier2d");
+
+type Builders = Map void>;
+
+class SimulationParameters {
+ backend: string;
+ prevBackend: string;
+ demo: string;
+ numSolverIters: number;
+ running: boolean;
+ stepping: boolean;
+ debugRender: boolean;
+ step: () => void;
+ restart: () => void;
+ takeSnapshot: () => void;
+ restoreSnapshot: () => void;
+ backends: Array;
+ builders: Builders;
+ debugInfos: boolean;
+
+ constructor(backends: Array, builders: Builders) {
+ this.backend = "rapier";
+ this.prevBackend = "rapier";
+ this.demo = "collision groups";
+ this.numSolverIters = 4;
+ this.running = true;
+ this.stepping = false;
+ this.debugRender = false;
+ this.step = function () {};
+ this.restart = function () {};
+ this.takeSnapshot = function () {};
+ this.restoreSnapshot = function () {};
+ this.backends = backends;
+ this.builders = builders;
+ this.debugInfos = false;
+ }
+}
+
+export class Testbed {
+ RAPIER: RAPIER_API;
+ gui: Gui;
+ graphics: Graphics;
+ inhibitLookAt: boolean;
+ parameters: SimulationParameters;
+ demoToken: number;
+ mouse: {x: number; y: number};
+ events: RAPIER.EventQueue;
+ world: RAPIER.World;
+ preTimestepAction?: (gfx: Graphics) => void;
+ stepId: number;
+ prevDemo: string;
+ lastMessageTime: number;
+ snap: Uint8Array;
+ snapStepId: number;
+
+ constructor(RAPIER: RAPIER_API, builders: Builders) {
+ let backends = ["rapier"];
+ this.RAPIER = RAPIER;
+ let parameters = new SimulationParameters(backends, builders);
+ this.gui = new Gui(this, parameters);
+ this.graphics = new Graphics();
+ this.inhibitLookAt = false;
+ this.parameters = parameters;
+ this.demoToken = 0;
+ this.mouse = {x: 0, y: 0};
+ this.events = new RAPIER.EventQueue(true);
+ this.switchToDemo(builders.keys().next().value);
+
+ window.addEventListener("mousemove", (event) => {
+ this.mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
+ this.mouse.y = 1 - (event.clientY / window.innerHeight) * 2;
+ });
+ }
+
+ setpreTimestepAction(action: (gfx: Graphics) => void) {
+ this.preTimestepAction = action;
+ }
+
+ setWorld(world: RAPIER.World) {
+ document.onkeyup = null;
+ document.onkeydown = null;
+ this.preTimestepAction = null;
+ this.world = world;
+ this.world.numSolverIterations = this.parameters.numSolverIters;
+ this.demoToken += 1;
+ this.stepId = 0;
+ this.gui.resetTiming();
+
+ world.forEachCollider((coll) => {
+ this.graphics.addCollider(this.RAPIER, world, coll);
+ });
+
+ this.lastMessageTime = new Date().getTime();
+ }
+
+ lookAt(pos: Parameters[0]) {
+ if (!this.inhibitLookAt) {
+ this.graphics.lookAt(pos);
+ }
+
+ this.inhibitLookAt = false;
+ }
+
+ switchToDemo(demo: string) {
+ if (demo == this.prevDemo) {
+ this.inhibitLookAt = true;
+ }
+
+ this.prevDemo = demo;
+ this.graphics.reset();
+ this.stepId = 0;
+
+ this.parameters.prevBackend = this.parameters.backend;
+ this.parameters.builders.get(demo)(this.RAPIER, this);
+ }
+
+ switchToBackend(backend: string) {
+ this.switchToDemo(this.parameters.demo);
+ }
+
+ takeSnapshot() {
+ this.snap = this.world.takeSnapshot();
+ this.snapStepId = this.stepId;
+ }
+
+ restoreSnapshot() {
+ if (!!this.snap) {
+ this.world.free();
+ this.world = this.RAPIER.World.restoreSnapshot(this.snap);
+ this.stepId = this.snapStepId;
+ }
+ }
+
+ run() {
+ if (this.parameters.running || this.parameters.stepping) {
+ this.world.numSolverIterations = this.parameters.numSolverIters;
+
+ if (!!this.preTimestepAction) {
+ this.preTimestepAction(this.graphics);
+ }
+
+ let t0 = new Date().getTime();
+ this.world.step(this.events);
+ this.gui.setTiming(new Date().getTime() - t0);
+ this.stepId += 1;
+
+ if (!!this.parameters.debugInfos) {
+ let t0 = performance.now();
+ let snapshot = this.world.takeSnapshot();
+ let t1 = performance.now();
+ let snapshotTime = t1 - t0;
+
+ let debugInfos: DebugInfos = {
+ token: this.demoToken,
+ stepId: this.stepId,
+ worldHash: "",
+ worldHashTime: 0,
+ snapshotTime: 0,
+ };
+ t0 = performance.now();
+ xxhash128(snapshot).then((hash) => {
+ debugInfos.worldHash = hash;
+ t1 = performance.now();
+ let worldHashTime = t1 - t0;
+ debugInfos.worldHashTime = worldHashTime;
+ debugInfos.snapshotTime = snapshotTime;
+ this.gui.setDebugInfos(debugInfos);
+ });
+ }
+ }
+
+ if (this.parameters.stepping) {
+ this.parameters.running = false;
+ this.parameters.stepping = false;
+ }
+
+ this.gui.stats.begin();
+ this.graphics.render(this.world, this.parameters.debugRender);
+ this.gui.stats.end();
+
+ requestAnimationFrame(() => this.run());
+ }
+}
diff --git a/typescript/testbed2d/src/demos/characterController.ts b/typescript/testbed2d/src/demos/characterController.ts
new file mode 100644
index 000000000..7877db12e
--- /dev/null
+++ b/typescript/testbed2d/src/demos/characterController.ts
@@ -0,0 +1,89 @@
+import type {Testbed} from "../Testbed";
+
+type RAPIER_API = typeof import("@dimforge/rapier2d");
+
+export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
+ let gravity = new RAPIER.Vector2(0.0, -9.81);
+ let world = new RAPIER.World(gravity);
+
+ // Create Ground.
+ let bodyDesc = RAPIER.RigidBodyDesc.fixed();
+ let body = world.createRigidBody(bodyDesc);
+ let colliderDesc = RAPIER.ColliderDesc.cuboid(15.0, 0.1);
+ world.createCollider(colliderDesc, body);
+
+ // Dynamic cubes.
+ let rad = 0.5;
+ let num = 5;
+ let i, j, k;
+ let shift = rad * 2.5;
+ let center = num * rad;
+ let height = 5.0;
+
+ for (i = 0; i < num; ++i) {
+ for (k = i; k < num; ++k) {
+ let x = (i * shift) / 2.0 + (k - i) * shift - center;
+ let y = (i * shift) / 2.0 + height;
+
+ // Create dynamic cube.
+ let bodyDesc = RAPIER.RigidBodyDesc.dynamic().setTranslation(x, y);
+ let body = world.createRigidBody(bodyDesc);
+ let colliderDesc = RAPIER.ColliderDesc.cuboid(rad, rad / 2.0);
+ world.createCollider(colliderDesc, body);
+ }
+ }
+
+ // Character.
+ let characterDesc =
+ RAPIER.RigidBodyDesc.kinematicPositionBased().setTranslation(
+ -10.0,
+ 4.0,
+ );
+ let character = world.createRigidBody(characterDesc);
+ let characterColliderDesc = RAPIER.ColliderDesc.cuboid(0.6, 1.2);
+ let characterCollider = world.createCollider(
+ characterColliderDesc,
+ character,
+ );
+
+ let characterController = world.createCharacterController(0.1);
+ characterController.enableAutostep(0.7, 0.3, true);
+ characterController.enableSnapToGround(0.7);
+
+ let speed = 0.2;
+ let movementDirection = {x: 0.0, y: -speed};
+
+ let updateCharacter = () => {
+ characterController.computeColliderMovement(
+ characterCollider,
+ movementDirection,
+ );
+
+ let movement = characterController.computedMovement();
+ let newPos = character.translation();
+ newPos.x += movement.x;
+ newPos.y += movement.y;
+ character.setNextKinematicTranslation(newPos);
+ console.log("here");
+ };
+
+ testbed.setWorld(world);
+ testbed.setpreTimestepAction(updateCharacter);
+
+ document.onkeydown = function (event: KeyboardEvent) {
+ if (event.key == "ArrowLeft") movementDirection.x = -speed;
+ if (event.key == "ArrowRight") movementDirection.x = speed;
+ if (event.key == " ") movementDirection.y = speed;
+ };
+
+ document.onkeyup = function (event: KeyboardEvent) {
+ if (event.key == "ArrowLeft") movementDirection.x = 0.0;
+ if (event.key == "ArrowRight") movementDirection.x = 0.0;
+ if (event.key == " ") movementDirection.y = -speed; // Gravity
+ };
+
+ testbed.lookAt({
+ target: {x: 0.0, y: -1.0},
+ zoom: 50.0,
+ });
+}
diff --git a/typescript/testbed2d/src/demos/collisionGroups.ts b/typescript/testbed2d/src/demos/collisionGroups.ts
new file mode 100644
index 000000000..511636181
--- /dev/null
+++ b/typescript/testbed2d/src/demos/collisionGroups.ts
@@ -0,0 +1,79 @@
+import type {Testbed} from "../Testbed";
+
+type RAPIER_API = typeof import("@dimforge/rapier2d");
+
+export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
+ let gravity = new RAPIER.Vector2(0.0, -9.81);
+ let world = new RAPIER.World(gravity);
+
+ /*
+ * Ground
+ */
+ let ground_size = 5.0;
+ let ground_height = 0.1;
+
+ let groundBodyDesc = RAPIER.RigidBodyDesc.fixed().setTranslation(
+ 0.0,
+ -ground_height,
+ );
+ let groundBody = world.createRigidBody(groundBodyDesc);
+ let colliderDesc = RAPIER.ColliderDesc.cuboid(ground_size, ground_height);
+ world.createCollider(colliderDesc, groundBody);
+
+ /*
+ * Setup groups
+ */
+ let group1 = 0x00010001;
+ let group2 = 0x00020002;
+
+ /*
+ * A green floor that will collide with the first group only.
+ */
+ colliderDesc = RAPIER.ColliderDesc.cuboid(1.0, 0.1)
+ .setTranslation(0.0, 1.0)
+ .setCollisionGroups(group1);
+ world.createCollider(colliderDesc, groundBody);
+
+ /*
+ * A blue floor that will collide with the second group only.
+ */
+ colliderDesc = RAPIER.ColliderDesc.cuboid(1.0, 0.1)
+ .setTranslation(0.0, 2.0)
+ .setCollisionGroups(group2);
+ world.createCollider(colliderDesc, groundBody);
+
+ /*
+ * Create the cubes
+ */
+ let num = 8;
+ let rad = 0.1;
+
+ let shift = rad * 2.0;
+ let centerx = shift * (num / 2);
+ let centery = 2.5;
+ let i, j;
+
+ for (j = 0; j < 4; ++j) {
+ for (i = 0; i < num; ++i) {
+ let x = i * shift - centerx;
+ let y = j * shift + centery;
+
+ // Alternate between the green and blue groups.
+ let group = i % 2 == 0 ? group1 : group2;
+
+ let bodyDesc = RAPIER.RigidBodyDesc.dynamic().setTranslation(x, y);
+ let body = world.createRigidBody(bodyDesc);
+ let colliderDesc = RAPIER.ColliderDesc.cuboid(
+ rad,
+ rad,
+ ).setCollisionGroups(group);
+ world.createCollider(colliderDesc, body);
+ }
+ }
+
+ testbed.setWorld(world);
+ testbed.lookAt({
+ target: {x: 0.0, y: -1.0},
+ zoom: 100.0,
+ });
+}
diff --git a/typescript/testbed2d/src/demos/convexPolygons.ts b/typescript/testbed2d/src/demos/convexPolygons.ts
new file mode 100644
index 000000000..6edad202f
--- /dev/null
+++ b/typescript/testbed2d/src/demos/convexPolygons.ts
@@ -0,0 +1,68 @@
+import seedrandom from "seedrandom";
+import type {Testbed} from "../Testbed";
+
+type RAPIER_API = typeof import("@dimforge/rapier2d");
+
+export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
+ let gravity = new RAPIER.Vector2(0.0, -9.81);
+ let world = new RAPIER.World(gravity);
+
+ /*
+ * Ground
+ */
+ // Create Ground.
+ let groundSize = 30.0;
+ let grounds = [
+ {x: 0.0, y: 0.0, hx: groundSize, hy: 1.2},
+ {x: -groundSize, y: groundSize, hx: 1.2, hy: groundSize},
+ {x: groundSize, y: groundSize, hx: 1.2, hy: groundSize},
+ ];
+
+ grounds.forEach((ground) => {
+ let bodyDesc = RAPIER.RigidBodyDesc.fixed().setTranslation(
+ ground.x,
+ ground.y,
+ );
+ let body = world.createRigidBody(bodyDesc);
+ let colliderDesc = RAPIER.ColliderDesc.cuboid(ground.hx, ground.hy);
+ world.createCollider(colliderDesc, body);
+ });
+
+ /*
+ * Create the convex polygons
+ */
+ let num = 14;
+ let scale = 4.0;
+
+ let shift = scale;
+ let centerx = (shift * num) / 2.0;
+ let centery = shift / 2.0;
+
+ let i, j, k;
+ let rng = seedrandom("convexPolygon");
+
+ for (i = 0; i < num; ++i) {
+ for (j = 0; j < num * 2; ++j) {
+ let x = i * shift - centerx;
+ let y = j * shift * 2.0 + centery + 2.0;
+
+ let bodyDesc = RAPIER.RigidBodyDesc.dynamic().setTranslation(x, y);
+ let body = world.createRigidBody(bodyDesc);
+
+ let points = [];
+ for (k = 0; k < 10; ++k) {
+ points.push(rng() * scale, rng() * scale);
+ }
+ let colliderDesc = RAPIER.ColliderDesc.convexHull(
+ new Float32Array(points),
+ );
+ world.createCollider(colliderDesc, body);
+ }
+ }
+
+ testbed.setWorld(world);
+ testbed.lookAt({
+ target: {x: -10.0, y: -30.0},
+ zoom: 7.0,
+ });
+}
diff --git a/typescript/testbed2d/src/demos/cubes.ts b/typescript/testbed2d/src/demos/cubes.ts
new file mode 100644
index 000000000..5214b485d
--- /dev/null
+++ b/typescript/testbed2d/src/demos/cubes.ts
@@ -0,0 +1,56 @@
+import type {Testbed} from "../Testbed";
+
+type RAPIER_API = typeof import("@dimforge/rapier2d");
+
+export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
+ let gravity = new RAPIER.Vector2(0.0, -9.81);
+ let world = new RAPIER.World(gravity);
+
+ // Create Ground.
+ let groundSize = 40.0;
+ let grounds = [
+ {x: 0.0, y: 0.0, hx: groundSize, hy: 0.1},
+ {x: -groundSize, y: groundSize, hx: 0.1, hy: groundSize},
+ {x: groundSize, y: groundSize, hx: 0.1, hy: groundSize},
+ ];
+
+ grounds.forEach((ground) => {
+ let bodyDesc = RAPIER.RigidBodyDesc.fixed().setTranslation(
+ ground.x,
+ ground.y,
+ );
+ let body = world.createRigidBody(bodyDesc);
+ let colliderDesc = RAPIER.ColliderDesc.cuboid(ground.hx, ground.hy);
+ world.createCollider(colliderDesc, body);
+ });
+
+ // Dynamic cubes.
+ let num = 20;
+ let numy = 50;
+ let rad = 1.0;
+
+ let shift = rad * 2.0 + rad;
+ let centerx = shift * (num / 2);
+ let centery = shift / 2.0;
+
+ let i, j;
+
+ for (j = 0; j < numy; ++j) {
+ for (i = 0; i < num; ++i) {
+ let x = i * shift - centerx;
+ let y = j * shift + centery + 3.0;
+
+ // Create dynamic cube.
+ let bodyDesc = RAPIER.RigidBodyDesc.dynamic().setTranslation(x, y);
+ let body = world.createRigidBody(bodyDesc);
+ let colliderDesc = RAPIER.ColliderDesc.cuboid(rad, rad);
+ world.createCollider(colliderDesc, body);
+ }
+ }
+
+ testbed.setWorld(world);
+ testbed.lookAt({
+ target: {x: -10.0, y: -30.0},
+ zoom: 7.0,
+ });
+}
diff --git a/typescript/testbed2d/src/demos/heightfield.ts b/typescript/testbed2d/src/demos/heightfield.ts
new file mode 100644
index 000000000..d055499b1
--- /dev/null
+++ b/typescript/testbed2d/src/demos/heightfield.ts
@@ -0,0 +1,65 @@
+import type {Testbed} from "../Testbed";
+
+type RAPIER_API = typeof import("@dimforge/rapier2d");
+
+export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
+ let gravity = new RAPIER.Vector2(0.0, -9.81);
+ let world = new RAPIER.World(gravity);
+ let i, j;
+
+ /*
+ * Ground
+ */
+ let ground_size = {x: 50.0, y: 1.0};
+ let nsubdivs = 100;
+ let heights = [];
+
+ heights.push(40.0);
+ for (i = 1; i < nsubdivs; ++i) {
+ heights.push(Math.cos((i * ground_size.x) / nsubdivs) * 2.0);
+ }
+ heights.push(40.0);
+
+ let bodyDesc = RAPIER.RigidBodyDesc.fixed();
+ let body = world.createRigidBody(bodyDesc);
+ let colliderDesc = RAPIER.ColliderDesc.heightfield(
+ new Float32Array(heights),
+ ground_size,
+ );
+ world.createCollider(colliderDesc, body);
+
+ /*
+ * Create the cubes
+ */
+ let num = 15;
+ let rad = 0.5;
+
+ let shift = rad * 2.0;
+ let centerx = shift * (num / 2);
+ let centery = shift / 2.0;
+
+ for (i = 0; i < num; ++i) {
+ for (j = 0; j < num * 5; ++j) {
+ let x = i * shift - centerx;
+ let y = j * shift + centery + 3.0;
+
+ // Build the rigid body.
+ let bodyDesc = RAPIER.RigidBodyDesc.dynamic().setTranslation(x, y);
+ let body = world.createRigidBody(bodyDesc);
+
+ if (j % 2 == 0) {
+ let colliderDesc = RAPIER.ColliderDesc.cuboid(rad, rad);
+ world.createCollider(colliderDesc, body);
+ } else {
+ let colliderDesc = RAPIER.ColliderDesc.ball(rad);
+ world.createCollider(colliderDesc, body);
+ }
+ }
+ }
+
+ testbed.setWorld(world);
+ testbed.lookAt({
+ target: {x: -10.0, y: -15.0},
+ zoom: 10.0,
+ });
+}
diff --git a/typescript/testbed2d/src/demos/keva.ts b/typescript/testbed2d/src/demos/keva.ts
new file mode 100644
index 000000000..6ca57c0cf
--- /dev/null
+++ b/typescript/testbed2d/src/demos/keva.ts
@@ -0,0 +1,92 @@
+import type * as RAPIER from "@dimforge/rapier2d";
+import type {Testbed} from "../Testbed";
+
+type RAPIER_API = typeof import("@dimforge/rapier2d");
+
+function buildBlock(
+ RAPIER: RAPIER_API,
+ world: RAPIER.World,
+ halfExtents: RAPIER.Vector,
+ shift: RAPIER.Vector,
+ numx: number,
+ numy: number,
+ numz: number,
+) {
+ let halfExtents_yx = {x: halfExtents.y, y: halfExtents.x};
+ let dimensions = [halfExtents, halfExtents_yx];
+ let spacing = (halfExtents.y * numx - halfExtents.x) / (numz - 1.0);
+
+ let i;
+ let j;
+ let y = 0.0;
+
+ for (i = 0; i <= numy; ++i) {
+ let dim = dimensions[i % 2];
+ [numx, numz] = [numz, numx];
+
+ for (j = 0; j < numx; ++j) {
+ let x = i % 2 == 0 ? spacing * j * 2.0 : dim.x * j * 2.0;
+
+ // Build the rigid body.
+ let bodyDesc = RAPIER.RigidBodyDesc.dynamic().setTranslation(
+ x + dim.x + shift.x,
+ y + dim.y + shift.y,
+ );
+ let body = world.createRigidBody(bodyDesc);
+ let colliderDesc = RAPIER.ColliderDesc.cuboid(dim.x, dim.y);
+ world.createCollider(colliderDesc, body);
+ }
+
+ y += dim.y * 2.0;
+ }
+}
+
+export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
+ let gravity = new RAPIER.Vector2(0.0, -9.81);
+ let world = new RAPIER.World(gravity);
+
+ // Create Ground.
+ let groundSize = 150.0;
+ let groundHeight = 0.1;
+ let bodyDesc = RAPIER.RigidBodyDesc.fixed().setTranslation(
+ 0.0,
+ -groundHeight,
+ );
+ let body = world.createRigidBody(bodyDesc);
+ let colliderDesc = RAPIER.ColliderDesc.cuboid(groundSize, groundHeight);
+ world.createCollider(colliderDesc, body);
+
+ // Keva tower.
+ let halfExtents = new RAPIER.Vector2(0.5, 2.0);
+ let blockHeight = 0.0;
+ // These should only be set to odd values otherwise
+ // the blocks won't align in the nicest way.
+ let numyArr = [0, 3, 5, 5, 7, 9];
+ let numBlocksBuilt = 0;
+ let i;
+
+ for (i = 5; i >= 1; --i) {
+ let numx = i * 15;
+ let numy = numyArr[i];
+ let numz = numx * 2 + 1;
+ let blockWidth = numx * halfExtents.y * 2.0;
+ buildBlock(
+ RAPIER,
+ world,
+ halfExtents,
+ new RAPIER.Vector2(-blockWidth / 2.0, blockHeight),
+ numx,
+ numy,
+ numz,
+ );
+ blockHeight += (numy + 1) * (halfExtents.x + halfExtents.y);
+ numBlocksBuilt += numx * numy;
+ }
+
+ testbed.setWorld(world);
+
+ testbed.lookAt({
+ target: {x: -10.0, y: -5.0},
+ zoom: 4.0,
+ });
+}
diff --git a/typescript/testbed2d/src/demos/lockedRotations.ts b/typescript/testbed2d/src/demos/lockedRotations.ts
new file mode 100644
index 000000000..8600f95f1
--- /dev/null
+++ b/typescript/testbed2d/src/demos/lockedRotations.ts
@@ -0,0 +1,51 @@
+import type {Testbed} from "../Testbed";
+
+type RAPIER_API = typeof import("@dimforge/rapier2d");
+
+export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
+ let gravity = new RAPIER.Vector2(0.0, -9.81);
+ let world = new RAPIER.World(gravity);
+
+ /*
+ * The ground
+ */
+ let ground_size = 1.8;
+ let ground_height = 1.0;
+
+ let bodyDesc = RAPIER.RigidBodyDesc.fixed().setTranslation(
+ 0.0,
+ -ground_height,
+ );
+ let body = world.createRigidBody(bodyDesc);
+ let colliderDesc = RAPIER.ColliderDesc.cuboid(ground_size, ground_height);
+ world.createCollider(colliderDesc, body);
+
+ /*
+ * A rectangle that only rotates along the `x` axis.
+ */
+ bodyDesc = RAPIER.RigidBodyDesc.dynamic()
+ .setTranslation(0.0, 3.0)
+ .lockTranslations();
+ body = world.createRigidBody(bodyDesc);
+ colliderDesc = RAPIER.ColliderDesc.cuboid(2.0, 0.6);
+ world.createCollider(colliderDesc, body);
+
+ /*
+ * A cuboid that cannot rotate.
+ */
+ bodyDesc = RAPIER.RigidBodyDesc.dynamic()
+ .setTranslation(0.4, 5.0)
+ .lockRotations();
+ body = world.createRigidBody(bodyDesc);
+ colliderDesc = RAPIER.ColliderDesc.cuboid(0.4, 0.6);
+ world.createCollider(colliderDesc, body);
+
+ /*
+ * Setup the testbed.
+ */
+ testbed.setWorld(world);
+ testbed.lookAt({
+ target: {x: 0.0, y: -2.0},
+ zoom: 50.0,
+ });
+}
diff --git a/typescript/testbed2d/src/demos/pidController.ts b/typescript/testbed2d/src/demos/pidController.ts
new file mode 100644
index 000000000..fac2a7c45
--- /dev/null
+++ b/typescript/testbed2d/src/demos/pidController.ts
@@ -0,0 +1,100 @@
+import type {Testbed} from "../Testbed";
+
+type RAPIER_API = typeof import("@dimforge/rapier2d");
+
+export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
+ let gravity = new RAPIER.Vector2(0.0, -9.81);
+ let world = new RAPIER.World(gravity);
+
+ // Create Ground.
+ let bodyDesc = RAPIER.RigidBodyDesc.fixed();
+ let body = world.createRigidBody(bodyDesc);
+ let colliderDesc = RAPIER.ColliderDesc.cuboid(15.0, 0.1);
+ world.createCollider(colliderDesc, body);
+
+ // Dynamic cubes.
+ let rad = 0.5;
+ let num = 5;
+ let i, j, k;
+ let shift = rad * 2.5;
+ let center = num * rad;
+ let height = 5.0;
+
+ for (i = 0; i < num; ++i) {
+ for (k = i; k < num; ++k) {
+ let x = (i * shift) / 2.0 + (k - i) * shift - center;
+ let y = (i * shift) / 2.0 + height;
+
+ // Create dynamic cube.
+ let bodyDesc = RAPIER.RigidBodyDesc.dynamic().setTranslation(x, y);
+ let body = world.createRigidBody(bodyDesc);
+ let colliderDesc = RAPIER.ColliderDesc.cuboid(rad, rad / 2.0);
+ world.createCollider(colliderDesc, body);
+ }
+ }
+
+ // Character.
+ let characterDesc = RAPIER.RigidBodyDesc.dynamic()
+ .setTranslation(-10.0, 4.0)
+ .setGravityScale(10.0)
+ .setSoftCcdPrediction(10.0);
+ let character = world.createRigidBody(characterDesc);
+ let characterColliderDesc = RAPIER.ColliderDesc.cuboid(0.6, 1.2);
+ world.createCollider(characterColliderDesc, character);
+
+ let pidController = world.createPidController(
+ 60.0,
+ 0.0,
+ 1.0,
+ RAPIER.PidAxesMask.AllAng,
+ );
+ let speed = 0.2;
+ let movementDirection = {x: 0.0, y: 0.0};
+ let targetVelocity = {x: 0.0, y: 0.0};
+ let targetRotation = 0.0;
+
+ let updateCharacter = () => {
+ if (movementDirection.x == 0.0 && movementDirection.y == 0.0) {
+ // Only adjust the rotation, but let translation.
+ pidController.setAxes(RAPIER.PidAxesMask.AllAng);
+ } else if (movementDirection.y == 0.0) {
+ // Don’t control the linear Y axis so the player can fall down due to gravity.
+ pidController.setAxes(
+ RAPIER.PidAxesMask.AllAng | RAPIER.PidAxesMask.LinX,
+ );
+ } else {
+ pidController.setAxes(RAPIER.PidAxesMask.All);
+ }
+
+ let targetPoint = character.translation();
+ targetPoint.x += movementDirection.x;
+ targetPoint.y += movementDirection.y;
+
+ pidController.applyLinearCorrection(
+ character,
+ targetPoint,
+ targetVelocity,
+ );
+ pidController.applyAngularCorrection(character, 0.0, 0.0);
+ };
+
+ testbed.setWorld(world);
+ testbed.setpreTimestepAction(updateCharacter);
+
+ document.onkeydown = function (event: KeyboardEvent) {
+ if (event.key == "ArrowLeft") movementDirection.x = -speed;
+ if (event.key == "ArrowRight") movementDirection.x = speed;
+ if (event.key == " ") movementDirection.y = speed;
+ };
+
+ document.onkeyup = function (event: KeyboardEvent) {
+ if (event.key == "ArrowLeft") movementDirection.x = 0.0;
+ if (event.key == "ArrowRight") movementDirection.x = 0.0;
+ if (event.key == " ") movementDirection.y = 0.0;
+ };
+
+ testbed.lookAt({
+ target: {x: 0.0, y: -1.0},
+ zoom: 50.0,
+ });
+}
diff --git a/typescript/testbed2d/src/demos/polyline.ts b/typescript/testbed2d/src/demos/polyline.ts
new file mode 100644
index 000000000..47d825401
--- /dev/null
+++ b/typescript/testbed2d/src/demos/polyline.ts
@@ -0,0 +1,64 @@
+import type {Testbed} from "../Testbed";
+
+type RAPIER_API = typeof import("@dimforge/rapier2d");
+
+export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
+ let gravity = new RAPIER.Vector2(0.0, -9.81);
+ let world = new RAPIER.World(gravity);
+ let i, j;
+
+ /*
+ * Ground
+ */
+ let nsubdivs = 100;
+ let points = [];
+ let groundSize = 30.0;
+ let stepSize = groundSize / nsubdivs;
+
+ points.push(-groundSize / 2.0, 25.0);
+ for (i = 1; i < nsubdivs; ++i) {
+ let x = -groundSize / 2.0 + i * stepSize;
+ let y = Math.cos(i * stepSize) * 2.0;
+ points.push(x, y);
+ }
+ points.push(groundSize / 2.0, 25.0);
+ let bodyDesc = RAPIER.RigidBodyDesc.fixed();
+ let body = world.createRigidBody(bodyDesc);
+ let colliderDesc = RAPIER.ColliderDesc.polyline(new Float32Array(points));
+ world.createCollider(colliderDesc, body);
+
+ /*
+ * Create the cubes
+ */
+ let num = 10;
+ let rad = 0.5;
+
+ let shift = rad * 2.0;
+ let centerx = shift * (num / 2);
+ let centery = shift / 2.0;
+
+ for (i = 0; i < num; ++i) {
+ for (j = 0; j < num * 5; ++j) {
+ let x = i * shift - centerx;
+ let y = j * shift + centery + 3.0;
+
+ // Build the rigid body.
+ let bodyDesc = RAPIER.RigidBodyDesc.dynamic().setTranslation(x, y);
+ let body = world.createRigidBody(bodyDesc);
+
+ if (j % 2 == 0) {
+ let colliderDesc = RAPIER.ColliderDesc.cuboid(rad, rad);
+ world.createCollider(colliderDesc, body);
+ } else {
+ let colliderDesc = RAPIER.ColliderDesc.ball(rad);
+ world.createCollider(colliderDesc, body);
+ }
+ }
+ }
+
+ testbed.setWorld(world);
+ testbed.lookAt({
+ target: {x: -10.0, y: -15.0},
+ zoom: 10.0,
+ });
+}
diff --git a/typescript/testbed2d/src/demos/revoluteJoints.ts b/typescript/testbed2d/src/demos/revoluteJoints.ts
new file mode 100644
index 000000000..2d7923fd5
--- /dev/null
+++ b/typescript/testbed2d/src/demos/revoluteJoints.ts
@@ -0,0 +1,59 @@
+import type {Testbed} from "../Testbed";
+
+type RAPIER_API = typeof import("@dimforge/rapier2d");
+
+export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
+ let gravity = new RAPIER.Vector2(0.0, -9.81);
+ let world = new RAPIER.World(gravity);
+ let bodies = [];
+
+ let rad = 0.4;
+ let numi = 30; // Num vertical nodes.
+ let numk = 30; // Num horizontal nodes.
+ let shift = 1.0;
+ let i, k;
+
+ for (k = 0; k < numk; ++k) {
+ for (i = 0; i < numi; ++i) {
+ let status =
+ k >= numk / 2 - 3 && k <= numk / 2 + 3 && i == 0
+ ? RAPIER.RigidBodyType.Fixed
+ : RAPIER.RigidBodyType.Dynamic;
+
+ let bodyDesc = new RAPIER.RigidBodyDesc(status).setTranslation(
+ k * shift,
+ -i * shift,
+ );
+ let child = world.createRigidBody(bodyDesc);
+ let colliderDesc = RAPIER.ColliderDesc.ball(rad);
+ world.createCollider(colliderDesc, child);
+
+ // Vertical joint.
+ if (i > 0) {
+ let parent = bodies[bodies.length - 1];
+ let anchor1 = new RAPIER.Vector2(0.0, 0.0);
+ let anchor2 = new RAPIER.Vector2(0.0, shift);
+ let JointData = RAPIER.JointData.revolute(anchor1, anchor2);
+ world.createImpulseJoint(JointData, parent, child, true);
+ }
+
+ // Horizontal joint.
+ if (k > 0) {
+ let parentIndex = bodies.length - numi;
+ let parent = bodies[parentIndex];
+ let anchor1 = new RAPIER.Vector2(0.0, 0.0);
+ let anchor2 = new RAPIER.Vector2(-shift, 0.0);
+ let JointData = RAPIER.JointData.revolute(anchor1, anchor2);
+ world.createImpulseJoint(JointData, parent, child, true);
+ }
+
+ bodies.push(child);
+ }
+ }
+
+ testbed.setWorld(world);
+ testbed.lookAt({
+ target: {x: 30.0, y: 30.0},
+ zoom: 10.0,
+ });
+}
diff --git a/typescript/testbed2d/src/demos/voxels.ts b/typescript/testbed2d/src/demos/voxels.ts
new file mode 100644
index 000000000..6a6fc3668
--- /dev/null
+++ b/typescript/testbed2d/src/demos/voxels.ts
@@ -0,0 +1,90 @@
+import type {Testbed} from "../Testbed";
+
+type RAPIER_API = typeof import("@dimforge/rapier2d");
+
+function generateVoxels(n: number) {
+ let points = [];
+
+ let i;
+ for (i = 0; i <= n; ++i) {
+ let y = Math.max(-0.8, Math.min(Math.sin((i / n) * 10.0), 0.8)) * 8.0;
+ points.push(i - n / 2.0, y);
+ }
+ return {
+ points: new Float32Array(points),
+ voxelSize: {x: 1.0, y: 1.2},
+ };
+}
+
+export function initWorld(RAPIER: RAPIER_API, testbed: Testbed) {
+ let gravity = new RAPIER.Vector2(0.0, -9.81);
+ let world = new RAPIER.World(gravity);
+
+ // Create Ground.
+ let bodyDesc = RAPIER.RigidBodyDesc.fixed();
+ let body = world.createRigidBody(bodyDesc);
+ let voxels = generateVoxels(100);
+ let colliderDesc = RAPIER.ColliderDesc.voxels(
+ voxels.points,
+ voxels.voxelSize,
+ );
+ world.createCollider(colliderDesc, body);
+
+ // Dynamic cubes.
+ let num = 10;
+ let numy = 4;
+ let rad = 1.0;
+
+ let shift = rad * 2.0 + rad;
+ let centery = shift / 2.0;
+
+ let offset = -num * (rad * 2.0 + rad) * 0.5;
+ let i, j;
+
+ for (j = 0; j < numy; ++j) {
+ for (i = 0; i < num; ++i) {
+ let x = i * shift + offset;
+ let y = j * shift + centery + 10.0;
+
+ // Create dynamic cube.
+ let bodyDesc = RAPIER.RigidBodyDesc.dynamic().setTranslation(x, y);
+ let body = world.createRigidBody(bodyDesc);
+ let colliderDesc;
+
+ switch (j % 3) {
+ case 0:
+ colliderDesc = RAPIER.ColliderDesc.cuboid(rad, rad);
+ break;
+ case 1:
+ colliderDesc = RAPIER.ColliderDesc.ball(rad);
+ break;
+ case 2:
+ colliderDesc = RAPIER.ColliderDesc.cuboid(
+ rad / 2.0,
+ rad / 2.0,
+ );
+ world.createCollider(colliderDesc, body);
+ colliderDesc = RAPIER.ColliderDesc.cuboid(
+ rad / 2.0,
+ rad,
+ ).setTranslation(rad, 0.0);
+ world.createCollider(colliderDesc, body);
+ colliderDesc = RAPIER.ColliderDesc.cuboid(
+ rad / 2.0,
+ rad,
+ ).setTranslation(-rad, 0.0);
+ break;
+ }
+
+ world.createCollider(colliderDesc, body);
+ }
+
+ offset -= 0.05 * rad * (num - 1.0);
+ }
+
+ testbed.setWorld(world);
+ testbed.lookAt({
+ target: {x: 0.0, y: 0.0},
+ zoom: 20.0,
+ });
+}
diff --git a/typescript/testbed2d/src/index.ts b/typescript/testbed2d/src/index.ts
new file mode 100644
index 000000000..24bd18f43
--- /dev/null
+++ b/typescript/testbed2d/src/index.ts
@@ -0,0 +1,30 @@
+import {Testbed} from "./Testbed";
+import * as CollisionGroups from "./demos/collisionGroups";
+import * as Cubes from "./demos/cubes";
+import * as Keva from "./demos/keva";
+import * as Heightfield from "./demos/heightfield";
+import * as Polyline from "./demos/polyline";
+import * as RevoluteJoints from "./demos/revoluteJoints";
+import * as LockedRotations from "./demos/lockedRotations";
+import * as ConvexPolygons from "./demos/convexPolygons";
+import * as CharacterController from "./demos/characterController";
+import * as PidController from "./demos/pidController";
+import * as Voxels from "./demos/voxels";
+
+import("@dimforge/rapier2d").then((RAPIER) => {
+ let builders = new Map([
+ ["collision groups", CollisionGroups.initWorld],
+ ["character controller", CharacterController.initWorld],
+ ["convex polygons", ConvexPolygons.initWorld],
+ ["cubes", Cubes.initWorld],
+ ["heightfield", Heightfield.initWorld],
+ ["joints: revolute", RevoluteJoints.initWorld],
+ ["keva tower", Keva.initWorld],
+ ["locked rotations", LockedRotations.initWorld],
+ ["pid controller", PidController.initWorld],
+ ["polyline", Polyline.initWorld],
+ ["voxels", Voxels.initWorld],
+ ]);
+ let testbed = new Testbed(RAPIER, builders);
+ testbed.run();
+});
diff --git a/typescript/testbed2d/static/.htaccess b/typescript/testbed2d/static/.htaccess
new file mode 100644
index 000000000..9bdb356b9
--- /dev/null
+++ b/typescript/testbed2d/static/.htaccess
@@ -0,0 +1,3 @@
+RewriteEngine On
+RewriteCond %{SERVER_PORT} 80
+RewriteRule ^(.*)$ https://www.rapier.rs/$1 [R,L]
diff --git a/typescript/testbed2d/static/index.html b/typescript/testbed2d/static/index.html
new file mode 100644
index 000000000..6df5b069c
--- /dev/null
+++ b/typescript/testbed2d/static/index.html
@@ -0,0 +1,18 @@
+
+
+
+
+ Rapier2D JS bindings demo
+
+
+
+
+
+
diff --git a/typescript/testbed2d/tsconfig.json b/typescript/testbed2d/tsconfig.json
new file mode 100644
index 000000000..5d07ecd80
--- /dev/null
+++ b/typescript/testbed2d/tsconfig.json
@@ -0,0 +1,11 @@
+{
+ "compilerOptions": {
+ "outDir": "./dist/",
+ "noImplicitAny": true,
+ "module": "es2022",
+ "target": "es2022",
+ "allowJs": true,
+ "moduleResolution": "node",
+ "allowSyntheticDefaultImports": true
+ }
+}
diff --git a/typescript/testbed2d/webpack.config.js b/typescript/testbed2d/webpack.config.js
new file mode 100644
index 000000000..0e5c98393
--- /dev/null
+++ b/typescript/testbed2d/webpack.config.js
@@ -0,0 +1,55 @@
+const webpack = require("webpack");
+const path = require("path");
+const CopyPlugin = require("copy-webpack-plugin");
+
+const isDev = process.env.NODE_ENV === "development";
+const dist = path.resolve(__dirname, "dist");
+
+/**
+ * @type {import('webpack-dev-server').Configuration}
+ */
+const devServer = {
+ static: {
+ directory: dist,
+ },
+ allowedHosts: "all",
+ compress: true,
+};
+
+/**
+ * @type {import('webpack').Configuration}
+ */
+const webpackConfig = {
+ mode: isDev ? "development" : "production",
+ entry: "./src/index.ts",
+ devtool: "inline-source-map",
+ output: {
+ path: dist,
+ filename: "index.js",
+ },
+ resolve: {
+ extensions: [".ts", ".js"],
+ },
+ devServer,
+ performance: false,
+ experiments: {
+ asyncWebAssembly: true,
+ syncWebAssembly: true,
+ },
+ module: {
+ rules: [
+ {
+ test: /\.tsx?$/,
+ use: "ts-loader",
+ exclude: /node_modules/,
+ },
+ ],
+ },
+ plugins: [
+ new CopyPlugin({
+ patterns: [{from: "static", to: dist}],
+ }),
+ ],
+};
+
+module.exports = webpackConfig;
diff --git a/typescript/testbed3d/.npmignore b/typescript/testbed3d/.npmignore
new file mode 100644
index 000000000..488f91257
--- /dev/null
+++ b/typescript/testbed3d/.npmignore
@@ -0,0 +1,3 @@
+webpack.config2d.js
+src
+*.tgz
\ No newline at end of file
diff --git a/typescript/testbed3d/package-lock.json b/typescript/testbed3d/package-lock.json
new file mode 100644
index 000000000..95727a7e4
--- /dev/null
+++ b/typescript/testbed3d/package-lock.json
@@ -0,0 +1,4373 @@
+{
+ "name": "rapier-testbed3d",
+ "version": "0.1.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "rapier-testbed3d",
+ "version": "0.1.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@dimforge/rapier3d": "file:../builds/rapier3d",
+ "hash-wasm": "^4.12.0",
+ "lil-gui": "^0.17.0",
+ "seedrandom": "^3.0.5",
+ "stats.js": "^0.17.0",
+ "three": "^0.146.0"
+ },
+ "devDependencies": {
+ "@types/seedrandom": "^3.0.2",
+ "@types/stats.js": "^0.17.0",
+ "@types/three": "^0.144.0",
+ "copy-webpack-plugin": "^11.0.0",
+ "rimraf": "^3.0.2",
+ "ts-loader": "^9.4.1",
+ "typescript": "^4.8.4",
+ "webpack": "^5.74.0",
+ "webpack-cli": "^4.10.0",
+ "webpack-dev-server": "^4.11.1"
+ }
+ },
+ "../builds/rapier3d": {
+ "name": "@dimforge/rapier3d",
+ "dependencies": {
+ "wasm-pack": "^0.12.1"
+ },
+ "devDependencies": {
+ "rimraf": "^3.0.2",
+ "typedoc": "^0.25.13"
+ }
+ },
+ "../rapier3d": {
+ "name": "@dimforge/rapier3d",
+ "extraneous": true,
+ "dependencies": {
+ "typescript": "^5.7.2",
+ "wasm-pack": "^0.12.1"
+ },
+ "devDependencies": {
+ "rimraf": "^3.0.2",
+ "typedoc": "^0.25.13"
+ }
+ },
+ "node_modules/@dimforge/rapier3d": {
+ "resolved": "../builds/rapier3d",
+ "link": true
+ },
+ "node_modules/@discoveryjs/json-ext": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
+ "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
+ "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/set-array": "^1.2.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "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/set-array": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
+ "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/source-map": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
+ "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.25"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
+ "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.25",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+ "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@leichtgewicht/ip-codec": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz",
+ "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "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"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "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"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@types/body-parser": {
+ "version": "1.19.5",
+ "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz",
+ "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/connect": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/bonjour": {
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz",
+ "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/connect": {
+ "version": "3.4.38",
+ "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
+ "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/connect-history-api-fallback": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz",
+ "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/express-serve-static-core": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/eslint": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz",
+ "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "*",
+ "@types/json-schema": "*"
+ }
+ },
+ "node_modules/@types/eslint-scope": {
+ "version": "3.7.7",
+ "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz",
+ "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/eslint": "*",
+ "@types/estree": "*"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
+ "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/express": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz",
+ "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/body-parser": "*",
+ "@types/express-serve-static-core": "^4.17.33",
+ "@types/qs": "*",
+ "@types/serve-static": "*"
+ }
+ },
+ "node_modules/@types/express-serve-static-core": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.2.tgz",
+ "integrity": "sha512-vluaspfvWEtE4vcSDlKRNer52DvOGrB2xv6diXy6UKyKW0lqZiWHGNApSyxOv+8DE5Z27IzVvE7hNkxg7EXIcg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "@types/qs": "*",
+ "@types/range-parser": "*",
+ "@types/send": "*"
+ }
+ },
+ "node_modules/@types/express/node_modules/@types/express-serve-static-core": {
+ "version": "4.19.6",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz",
+ "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "@types/qs": "*",
+ "@types/range-parser": "*",
+ "@types/send": "*"
+ }
+ },
+ "node_modules/@types/http-errors": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz",
+ "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/http-proxy": {
+ "version": "1.17.15",
+ "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.15.tgz",
+ "integrity": "sha512-25g5atgiVNTIv0LBDTg1H74Hvayx0ajtJPLLcYE3whFv75J0pWNtOBzaXJQgDTmrX1bx5U9YC2w/n65BN1HwRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "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,
+ "license": "MIT"
+ },
+ "node_modules/@types/mime": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
+ "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/node": {
+ "version": "22.10.1",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.1.tgz",
+ "integrity": "sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.20.0"
+ }
+ },
+ "node_modules/@types/node-forge": {
+ "version": "1.3.11",
+ "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz",
+ "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/qs": {
+ "version": "6.9.17",
+ "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.17.tgz",
+ "integrity": "sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/range-parser": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
+ "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/retry": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz",
+ "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/seedrandom": {
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-3.0.8.tgz",
+ "integrity": "sha512-TY1eezMU2zH2ozQoAFAQFOPpvP15g+ZgSfTZt31AUUH/Rxtnz3H+A/Sv1Snw2/amp//omibc+AEkTaA8KUeOLQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/send": {
+ "version": "0.17.4",
+ "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz",
+ "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/mime": "^1",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/serve-index": {
+ "version": "1.9.4",
+ "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz",
+ "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/express": "*"
+ }
+ },
+ "node_modules/@types/serve-static": {
+ "version": "1.15.7",
+ "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz",
+ "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/http-errors": "*",
+ "@types/node": "*",
+ "@types/send": "*"
+ }
+ },
+ "node_modules/@types/sockjs": {
+ "version": "0.3.36",
+ "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz",
+ "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/stats.js": {
+ "version": "0.17.3",
+ "resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.3.tgz",
+ "integrity": "sha512-pXNfAD3KHOdif9EQXZ9deK82HVNaXP5ZIF5RP2QG6OQFNTaY2YIetfrE9t528vEreGQvEPRDDc8muaoYeK0SxQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/three": {
+ "version": "0.144.0",
+ "resolved": "https://registry.npmjs.org/@types/three/-/three-0.144.0.tgz",
+ "integrity": "sha512-psvEs6q5rLN50jUYZ3D4pZMfxTbdt3A243blt0my7/NcL6chaCZpHe2csbCtx0SOD9fI/XnF3wnVUAYZGqCSYg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/webxr": "*"
+ }
+ },
+ "node_modules/@types/webxr": {
+ "version": "0.5.20",
+ "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.20.tgz",
+ "integrity": "sha512-JGpU6qiIJQKUuVSKx1GtQnHJGxRjtfGIhzO2ilq43VZZS//f1h1Sgexbdk+Lq+7569a6EYhOWrUpIruR/1Enmg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/ws": {
+ "version": "8.5.13",
+ "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz",
+ "integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "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",
+ "dependencies": {
+ "@webassemblyjs/helper-numbers": "1.13.2",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2"
+ }
+ },
+ "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"
+ },
+ "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"
+ },
+ "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,
+ "license": "MIT"
+ },
+ "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",
+ "dependencies": {
+ "@webassemblyjs/floating-point-hex-parser": "1.13.2",
+ "@webassemblyjs/helper-api-error": "1.13.2",
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "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,
+ "license": "MIT"
+ },
+ "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,
+ "license": "MIT",
+ "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/@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",
+ "dependencies": {
+ "@xtuc/ieee754": "^1.2.0"
+ }
+ },
+ "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",
+ "dependencies": {
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "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,
+ "license": "MIT"
+ },
+ "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",
+ "dependencies": {
+ "@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/@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,
+ "license": "MIT",
+ "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/@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",
+ "dependencies": {
+ "@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/@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",
+ "dependencies": {
+ "@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/@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",
+ "dependencies": {
+ "@webassemblyjs/ast": "1.14.1",
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "node_modules/@webpack-cli/configtest": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz",
+ "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "webpack": "4.x.x || 5.x.x",
+ "webpack-cli": "4.x.x"
+ }
+ },
+ "node_modules/@webpack-cli/info": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.5.0.tgz",
+ "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "envinfo": "^7.7.3"
+ },
+ "peerDependencies": {
+ "webpack-cli": "4.x.x"
+ }
+ },
+ "node_modules/@webpack-cli/serve": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz",
+ "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "webpack-cli": "4.x.x"
+ },
+ "peerDependenciesMeta": {
+ "webpack-dev-server": {
+ "optional": true
+ }
+ }
+ },
+ "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,
+ "license": "BSD-3-Clause"
+ },
+ "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"
+ },
+ "node_modules/accepts": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
+ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mime-types": "~2.1.34",
+ "negotiator": "0.6.3"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/accepts/node_modules/negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.14.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
+ "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "8.17.1",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
+ "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
+ "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/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": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "ajv": {
+ "optional": true
+ }
+ }
+ },
+ "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/ansi-html-community": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz",
+ "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==",
+ "dev": true,
+ "engines": [
+ "node >= 0.8.0"
+ ],
+ "license": "Apache-2.0",
+ "bin": {
+ "ansi-html": "bin/ansi-html"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "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,
+ "license": "ISC",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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,
+ "license": "MIT"
+ },
+ "node_modules/batch": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
+ "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==",
+ "dev": true,
+ "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": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/body-parser": {
+ "version": "1.20.3",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
+ "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "3.1.2",
+ "content-type": "~1.0.5",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "on-finished": "2.4.1",
+ "qs": "6.13.0",
+ "raw-body": "2.5.2",
+ "type-is": "~1.6.18",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/bonjour-service": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.3.0.tgz",
+ "integrity": "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "multicast-dns": "^7.2.5"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "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": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.24.2",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz",
+ "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==",
+ "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": {
+ "caniuse-lite": "^1.0.30001669",
+ "electron-to-chromium": "^1.5.41",
+ "node-releases": "^2.0.18",
+ "update-browserslist-db": "^1.1.1"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "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/bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
+ "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "set-function-length": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001686",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001686.tgz",
+ "integrity": "sha512-Y7deg0Aergpa24M3qLC5xjNklnKnhsmSyR/V89dLZ1n0ucJIFNs7PgR2Yfa/Zf6W79SbBicgtGxZr2juHkEUIA==",
+ "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": "CC-BY-4.0"
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "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/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": {
+ "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"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ },
+ "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,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "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,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0"
+ }
+ },
+ "node_modules/clone-deep": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
+ "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-plain-object": "^2.0.4",
+ "kind-of": "^6.0.2",
+ "shallow-clone": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/colorette": {
+ "version": "2.0.20",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
+ "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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"
+ },
+ "node_modules/compressible": {
+ "version": "2.0.18",
+ "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
+ "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": ">= 1.43.0 < 2"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/compression": {
+ "version": "1.7.5",
+ "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.5.tgz",
+ "integrity": "sha512-bQJ0YRck5ak3LgtnpKkiabX5pNF7tMUh1BSy2ZBOTh0Dim0BUu6aPPwByIns6/A5Prh8PufSPerMDUklpzes2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "3.1.2",
+ "compressible": "~2.0.18",
+ "debug": "2.6.9",
+ "negotiator": "~0.6.4",
+ "on-headers": "~1.0.2",
+ "safe-buffer": "5.2.1",
+ "vary": "~1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "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/connect-history-api-fallback": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz",
+ "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/content-disposition": {
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
+ "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "5.2.1"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/content-type": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
+ "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/copy-webpack-plugin": {
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz",
+ "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-glob": "^3.2.11",
+ "glob-parent": "^6.0.1",
+ "globby": "^13.1.1",
+ "normalize-path": "^3.0.0",
+ "schema-utils": "^4.0.0",
+ "serialize-javascript": "^6.0.0"
+ },
+ "engines": {
+ "node": ">= 14.15.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "^5.1.0"
+ }
+ },
+ "node_modules/core-util-is": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/default-gateway": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz",
+ "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "execa": "^5.0.0"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/define-lazy-prop": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
+ "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/destroy": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
+ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/detect-node": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz",
+ "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/dns-packet": {
+ "version": "5.6.1",
+ "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz",
+ "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@leichtgewicht/ip-codec": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.68",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.68.tgz",
+ "integrity": "sha512-FgMdJlma0OzUYlbrtZ4AeXjKxKPk6KT8WOP8BjcqxWtlg8qyJQjRzPJzUtUn5GBg1oQ26hFs7HOOHJMYiJRnvQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/encodeurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
+ "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/enhanced-resolve": {
+ "version": "5.17.1",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz",
+ "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.4",
+ "tapable": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/envinfo": {
+ "version": "7.14.0",
+ "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz",
+ "integrity": "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "envinfo": "dist/cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
+ "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "get-intrinsic": "^1.2.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-module-lexer": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz",
+ "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "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": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esrecurse/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": ">=4.0"
+ }
+ },
+ "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",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/eventemitter3": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
+ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/events": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.x"
+ }
+ },
+ "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": {
+ "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"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/express": {
+ "version": "4.21.1",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz",
+ "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "accepts": "~1.3.8",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.20.3",
+ "content-disposition": "0.5.4",
+ "content-type": "~1.0.4",
+ "cookie": "0.7.1",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "1.3.1",
+ "fresh": "0.5.2",
+ "http-errors": "2.0.0",
+ "merge-descriptors": "1.0.3",
+ "methods": "~1.1.2",
+ "on-finished": "2.4.1",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "0.1.10",
+ "proxy-addr": "~2.0.7",
+ "qs": "6.13.0",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.2.1",
+ "send": "0.19.0",
+ "serve-static": "1.16.2",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "type-is": "~1.6.18",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.10.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/fast-glob": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
+ "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
+ "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"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "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": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "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,
+ "license": "MIT"
+ },
+ "node_modules/fast-uri": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz",
+ "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/fastest-levenshtein": {
+ "version": "1.0.16",
+ "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz",
+ "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4.9.1"
+ }
+ },
+ "node_modules/fastq": {
+ "version": "1.17.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
+ "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/faye-websocket": {
+ "version": "0.11.4",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz",
+ "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "websocket-driver": ">=0.5.1"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "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": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/finalhandler": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz",
+ "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "2.6.9",
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "on-finished": "2.4.1",
+ "parseurl": "~1.3.3",
+ "statuses": "2.0.1",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "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/flat": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
+ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "bin": {
+ "flat": "cli.js"
+ }
+ },
+ "node_modules/follow-redirects": {
+ "version": "1.15.9",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
+ "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/forwarded": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fs-monkey": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz",
+ "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==",
+ "dev": true,
+ "license": "Unlicense"
+ },
+ "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/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
+ "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "hasown": "^2.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Glob versions prior to v9 are no longer supported",
+ "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/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": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "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,
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/globby": {
+ "version": "13.2.2",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz",
+ "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.3.0",
+ "ignore": "^5.2.4",
+ "merge2": "^1.4.1",
+ "slash": "^4.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/handle-thing": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz",
+ "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-proto": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.1.0.tgz",
+ "integrity": "sha512-QLdzI9IIO1Jg7f9GT1gXpPpXArAn6cS31R1eEZqz08Gc+uQ8/XiqHWt17Fiw+2p6oTTIq5GXEpQkAlA88YRl/Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hash-wasm": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/hash-wasm/-/hash-wasm-4.12.0.tgz",
+ "integrity": "sha512-+/2B2rYLb48I/evdOIhP+K/DD2ca2fgBjp6O+GBEnCDk2e4rpeXIK8GvIyRPjTezgmWn9gmKwkQjjx6BtqDHVQ==",
+ "license": "MIT"
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/hpack.js": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
+ "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.1",
+ "obuf": "^1.0.0",
+ "readable-stream": "^2.0.1",
+ "wbuf": "^1.1.0"
+ }
+ },
+ "node_modules/hpack.js/node_modules/readable-stream": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/hpack.js/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/hpack.js/node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/html-entities": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz",
+ "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/mdevils"
+ },
+ {
+ "type": "patreon",
+ "url": "https://patreon.com/mdevils"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/http-deceiver": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
+ "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/http-errors": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
+ "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "depd": "2.0.0",
+ "inherits": "2.0.4",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "toidentifier": "1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/http-parser-js": {
+ "version": "0.5.8",
+ "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz",
+ "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/http-proxy": {
+ "version": "1.18.1",
+ "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
+ "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eventemitter3": "^4.0.0",
+ "follow-redirects": "^1.0.0",
+ "requires-port": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/http-proxy-middleware": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz",
+ "integrity": "sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/http-proxy": "^1.17.8",
+ "http-proxy": "^1.18.1",
+ "is-glob": "^4.0.1",
+ "is-plain-obj": "^3.0.0",
+ "micromatch": "^4.0.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "@types/express": "^4.17.13"
+ },
+ "peerDependenciesMeta": {
+ "@types/express": {
+ "optional": 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/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "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,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-local": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz",
+ "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "pkg-dir": "^4.2.0",
+ "resolve-cwd": "^3.0.0"
+ },
+ "bin": {
+ "import-local-fixture": "fixtures/cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/interpret": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz",
+ "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/ipaddr.js": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz",
+ "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "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": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.15.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz",
+ "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-docker": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
+ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "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,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-plain-obj": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz",
+ "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "isobject": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "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/is-wsl": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
+ "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-docker": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
+ "dev": true,
+ "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/isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ }
+ },
+ "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",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "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,
+ "license": "MIT"
+ },
+ "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/kind-of": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/launch-editor": {
+ "version": "2.9.1",
+ "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.9.1.tgz",
+ "integrity": "sha512-Gcnl4Bd+hRO9P9icCP/RVVT2o8SFlPXofuCxvA2SaZuH45whSvf5p8x5oih5ftLiVhEI4sp5xDY+R+b3zJBh5w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "picocolors": "^1.0.0",
+ "shell-quote": "^1.8.1"
+ }
+ },
+ "node_modules/lil-gui": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/lil-gui/-/lil-gui-0.17.0.tgz",
+ "integrity": "sha512-MVBHmgY+uEbmJNApAaPbtvNh1RCAeMnKym82SBjtp5rODTYKWtM+MXHCifLe2H2Ti1HuBGBtK/5SyG4ShQ3pUQ==",
+ "license": "MIT"
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.11.5"
+ }
+ },
+ "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/media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/memfs": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz",
+ "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==",
+ "dev": true,
+ "license": "Unlicense",
+ "dependencies": {
+ "fs-monkey": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/merge-descriptors": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
+ "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "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": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "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,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/minimalistic-assert": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
+ "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/multicast-dns": {
+ "version": "7.2.5",
+ "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz",
+ "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dns-packet": "^5.2.2",
+ "thunky": "^1.0.2"
+ },
+ "bin": {
+ "multicast-dns": "cli.js"
+ }
+ },
+ "node_modules/negotiator": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz",
+ "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "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,
+ "license": "MIT"
+ },
+ "node_modules/node-forge": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
+ "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
+ "dev": true,
+ "license": "(BSD-3-Clause OR GPL-2.0)",
+ "engines": {
+ "node": ">= 6.13.0"
+ }
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.18",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz",
+ "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "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": {
+ "path-key": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.13.3",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz",
+ "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/obuf": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
+ "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/on-finished": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/on-headers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
+ "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "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,
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "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": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/open": {
+ "version": "8.4.2",
+ "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz",
+ "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-lazy-prop": "^2.0.0",
+ "is-docker": "^2.1.1",
+ "is-wsl": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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/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/p-retry": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz",
+ "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/retry": "0.12.0",
+ "retry": "^0.13.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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": ">=6"
+ }
+ },
+ "node_modules/parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "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/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,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "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,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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-to-regexp": {
+ "version": "0.1.10",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz",
+ "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "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": ">=8"
+ }
+ },
+ "node_modules/process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/proxy-addr": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "forwarded": "0.2.0",
+ "ipaddr.js": "1.9.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/proxy-addr/node_modules/ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "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": ">=6"
+ }
+ },
+ "node_modules/qs": {
+ "version": "6.13.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
+ "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "side-channel": "^1.0.6"
+ },
+ "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/range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/raw-body": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
+ "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "3.1.2",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "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/rechoir": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz",
+ "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "resolve": "^1.9.0"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "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/requires-port": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/resolve": {
+ "version": "1.22.8",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
+ "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-cwd": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+ "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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/retry": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
+ "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "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/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/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==",
+ "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/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/schema-utils": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz",
+ "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==",
+ "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": ">= 12.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
+ "node_modules/seedrandom": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz",
+ "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==",
+ "license": "MIT"
+ },
+ "node_modules/select-hose": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
+ "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/selfsigned": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz",
+ "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node-forge": "^1.3.0",
+ "node-forge": "^1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/send": {
+ "version": "0.19.0",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
+ "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "2.0.0",
+ "mime": "1.6.0",
+ "ms": "2.1.3",
+ "on-finished": "2.4.1",
+ "range-parser": "~1.2.1",
+ "statuses": "2.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/send/node_modules/encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/send/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,
+ "license": "MIT"
+ },
+ "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/serve-index": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
+ "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "accepts": "~1.3.4",
+ "batch": "0.6.1",
+ "debug": "2.6.9",
+ "escape-html": "~1.0.3",
+ "http-errors": "~1.6.2",
+ "mime-types": "~2.1.17",
+ "parseurl": "~1.3.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/serve-index/node_modules/depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/serve-index/node_modules/http-errors": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
+ "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "depd": "~1.1.2",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.1.0",
+ "statuses": ">= 1.4.0 < 2"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/serve-index/node_modules/inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/serve-index/node_modules/setprototypeof": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
+ "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/serve-index/node_modules/statuses": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+ "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/serve-static": {
+ "version": "1.16.2",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
+ "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "0.19.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "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/setprototypeof": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/shallow-clone": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
+ "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "kind-of": "^6.0.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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/shell-quote": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz",
+ "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
+ "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.4",
+ "object-inspect": "^1.13.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/slash": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz",
+ "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/sockjs": {
+ "version": "0.3.24",
+ "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz",
+ "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "faye-websocket": "^0.11.3",
+ "uuid": "^8.3.2",
+ "websocket-driver": "^0.7.4"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.7.4",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
+ "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "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/source-map-support/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/spdy": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz",
+ "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.1.0",
+ "handle-thing": "^2.0.0",
+ "http-deceiver": "^1.2.7",
+ "select-hose": "^2.0.0",
+ "spdy-transport": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/spdy-transport": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz",
+ "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.1.0",
+ "detect-node": "^2.0.4",
+ "hpack.js": "^2.1.6",
+ "obuf": "^1.1.2",
+ "readable-stream": "^3.0.6",
+ "wbuf": "^1.7.3"
+ }
+ },
+ "node_modules/spdy-transport/node_modules/debug": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/spdy-transport/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,
+ "license": "MIT"
+ },
+ "node_modules/spdy/node_modules/debug": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/spdy/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,
+ "license": "MIT"
+ },
+ "node_modules/stats.js": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/stats.js/-/stats.js-0.17.0.tgz",
+ "integrity": "sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw==",
+ "license": "MIT"
+ },
+ "node_modules/statuses": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
+ "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "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/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==",
+ "dev": true,
+ "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/tapable": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
+ "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/terser": {
+ "version": "5.36.0",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz",
+ "integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "@jridgewell/source-map": "^0.3.3",
+ "acorn": "^8.8.2",
+ "commander": "^2.20.0",
+ "source-map-support": "~0.5.20"
+ },
+ "bin": {
+ "terser": "bin/terser"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/terser-webpack-plugin": {
+ "version": "5.3.10",
+ "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz",
+ "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.20",
+ "jest-worker": "^27.4.5",
+ "schema-utils": "^3.1.1",
+ "serialize-javascript": "^6.0.1",
+ "terser": "^5.26.0"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ },
+ "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
+ }
+ }
+ },
+ "node_modules/terser-webpack-plugin/node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "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"
+ }
+ },
+ "node_modules/terser-webpack-plugin/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==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "ajv": "^6.9.1"
+ }
+ },
+ "node_modules/terser-webpack-plugin/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/terser-webpack-plugin/node_modules/schema-utils": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
+ "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
+ "dev": true,
+ "license": "MIT",
+ "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/three": {
+ "version": "0.146.0",
+ "resolved": "https://registry.npmjs.org/three/-/three-0.146.0.tgz",
+ "integrity": "sha512-1lvNfLezN6OJ9NaFAhfX4sm5e9YCzHtaRgZ1+B4C+Hv6TibRMsuBAM5/wVKzxjpYIlMymvgsHEFrrigEfXnb2A==",
+ "license": "MIT"
+ },
+ "node_modules/thunky": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz",
+ "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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/toidentifier": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/ts-loader": {
+ "version": "9.5.1",
+ "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz",
+ "integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "enhanced-resolve": "^5.0.0",
+ "micromatch": "^4.0.0",
+ "semver": "^7.3.4",
+ "source-map": "^0.7.4"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "typescript": "*",
+ "webpack": "^5.0.0"
+ }
+ },
+ "node_modules/type-is": {
+ "version": "1.6.18",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "4.9.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
+ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "6.20.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
+ "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz",
+ "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==",
+ "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.0"
+ },
+ "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/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,
+ "license": "MIT"
+ },
+ "node_modules/utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "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,
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
+ "node_modules/vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/watchpack": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz",
+ "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "glob-to-regexp": "^0.4.1",
+ "graceful-fs": "^4.1.2"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/wbuf": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz",
+ "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "minimalistic-assert": "^1.0.0"
+ }
+ },
+ "node_modules/webpack": {
+ "version": "5.97.0",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.0.tgz",
+ "integrity": "sha512-CWT8v7ShSfj7tGs4TLRtaOLmOCPWhoKEvp+eA7FVx8Xrjb3XfT0aXdxDItnRZmE8sHcH+a8ayDrJCOjXKxVFfQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/eslint-scope": "^3.7.7",
+ "@types/estree": "^1.0.6",
+ "@webassemblyjs/ast": "^1.14.1",
+ "@webassemblyjs/wasm-edit": "^1.14.1",
+ "@webassemblyjs/wasm-parser": "^1.14.1",
+ "acorn": "^8.14.0",
+ "browserslist": "^4.24.0",
+ "chrome-trace-event": "^1.0.2",
+ "enhanced-resolve": "^5.17.1",
+ "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.11",
+ "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.2.0",
+ "tapable": "^2.1.1",
+ "terser-webpack-plugin": "^5.3.10",
+ "watchpack": "^2.4.1",
+ "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-cli": {
+ "version": "4.10.0",
+ "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz",
+ "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@discoveryjs/json-ext": "^0.5.0",
+ "@webpack-cli/configtest": "^1.2.0",
+ "@webpack-cli/info": "^1.5.0",
+ "@webpack-cli/serve": "^1.7.0",
+ "colorette": "^2.0.14",
+ "commander": "^7.0.0",
+ "cross-spawn": "^7.0.3",
+ "fastest-levenshtein": "^1.0.12",
+ "import-local": "^3.0.2",
+ "interpret": "^2.2.0",
+ "rechoir": "^0.7.0",
+ "webpack-merge": "^5.7.3"
+ },
+ "bin": {
+ "webpack-cli": "bin/cli.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "4.x.x || 5.x.x"
+ },
+ "peerDependenciesMeta": {
+ "@webpack-cli/generators": {
+ "optional": true
+ },
+ "@webpack-cli/migrate": {
+ "optional": true
+ },
+ "webpack-bundle-analyzer": {
+ "optional": true
+ },
+ "webpack-dev-server": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/webpack-cli/node_modules/commander": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
+ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/webpack-dev-middleware": {
+ "version": "5.3.4",
+ "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz",
+ "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "colorette": "^2.0.10",
+ "memfs": "^3.4.3",
+ "mime-types": "^2.1.31",
+ "range-parser": "^1.2.1",
+ "schema-utils": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 12.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "^4.0.0 || ^5.0.0"
+ }
+ },
+ "node_modules/webpack-dev-server": {
+ "version": "4.15.2",
+ "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz",
+ "integrity": "sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/bonjour": "^3.5.9",
+ "@types/connect-history-api-fallback": "^1.3.5",
+ "@types/express": "^4.17.13",
+ "@types/serve-index": "^1.9.1",
+ "@types/serve-static": "^1.13.10",
+ "@types/sockjs": "^0.3.33",
+ "@types/ws": "^8.5.5",
+ "ansi-html-community": "^0.0.8",
+ "bonjour-service": "^1.0.11",
+ "chokidar": "^3.5.3",
+ "colorette": "^2.0.10",
+ "compression": "^1.7.4",
+ "connect-history-api-fallback": "^2.0.0",
+ "default-gateway": "^6.0.3",
+ "express": "^4.17.3",
+ "graceful-fs": "^4.2.6",
+ "html-entities": "^2.3.2",
+ "http-proxy-middleware": "^2.0.3",
+ "ipaddr.js": "^2.0.1",
+ "launch-editor": "^2.6.0",
+ "open": "^8.0.9",
+ "p-retry": "^4.5.0",
+ "rimraf": "^3.0.2",
+ "schema-utils": "^4.0.0",
+ "selfsigned": "^2.1.1",
+ "serve-index": "^1.9.1",
+ "sockjs": "^0.3.24",
+ "spdy": "^4.0.2",
+ "webpack-dev-middleware": "^5.3.4",
+ "ws": "^8.13.0"
+ },
+ "bin": {
+ "webpack-dev-server": "bin/webpack-dev-server.js"
+ },
+ "engines": {
+ "node": ">= 12.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "^4.37.0 || ^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "webpack": {
+ "optional": true
+ },
+ "webpack-cli": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/webpack-merge": {
+ "version": "5.10.0",
+ "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz",
+ "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "clone-deep": "^4.0.1",
+ "flat": "^5.0.2",
+ "wildcard": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "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,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/webpack/node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "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"
+ }
+ },
+ "node_modules/webpack/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==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "ajv": "^6.9.1"
+ }
+ },
+ "node_modules/webpack/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/webpack/node_modules/schema-utils": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
+ "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
+ "dev": true,
+ "license": "MIT",
+ "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/websocket-driver": {
+ "version": "0.7.4",
+ "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
+ "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "http-parser-js": ">=0.5.1",
+ "safe-buffer": ">=5.1.0",
+ "websocket-extensions": ">=0.1.1"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/websocket-extensions": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz",
+ "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "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/wildcard": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz",
+ "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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/ws": {
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
+ "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ }
+ }
+}
diff --git a/typescript/testbed3d/package.json b/typescript/testbed3d/package.json
new file mode 100644
index 000000000..516ee2757
--- /dev/null
+++ b/typescript/testbed3d/package.json
@@ -0,0 +1,32 @@
+{
+ "author": "sebcrozet ",
+ "name": "rapier-testbed3d",
+ "version": "0.1.0",
+ "description": "JavaScript testbed for rapier.",
+ "license": "Apache-2.0",
+ "main": "dist/rapier-testbed3d.js",
+ "scripts": {
+ "build": "rimraf dist pkg && webpack",
+ "start": "rimraf dist pkg && webpack serve --open --node-env development"
+ },
+ "dependencies": {
+ "@dimforge/rapier3d": "file:../builds/rapier3d",
+ "hash-wasm": "^4.12.0",
+ "lil-gui": "^0.17.0",
+ "seedrandom": "^3.0.5",
+ "stats.js": "^0.17.0",
+ "three": "^0.146.0"
+ },
+ "devDependencies": {
+ "@types/seedrandom": "^3.0.2",
+ "@types/stats.js": "^0.17.0",
+ "@types/three": "^0.144.0",
+ "copy-webpack-plugin": "^11.0.0",
+ "rimraf": "^3.0.2",
+ "ts-loader": "^9.4.1",
+ "typescript": "^4.8.4",
+ "webpack": "^5.74.0",
+ "webpack-cli": "^4.10.0",
+ "webpack-dev-server": "^4.11.1"
+ }
+}
diff --git a/typescript/testbed3d/publish.sh b/typescript/testbed3d/publish.sh
new file mode 100755
index 000000000..e8bc248f1
--- /dev/null
+++ b/typescript/testbed3d/publish.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+npm run build
+rsync -av --delete-after dist/ crozet@ssh.cluster003.hosting.ovh.net:/home/crozet/rapier/demos3d
+# rsync -av dist/ammo.wasm.wasm crozet@ssh.cluster003.hosting.ovh.net:/home/crozet/rapier/ammo.wasm.wasm
+# rsync -av dist/physx.release.wasm crozet@ssh.cluster003.hosting.ovh.net:/home/crozet/rapier/physx.release.wasm
diff --git a/typescript/testbed3d/src/Graphics.ts b/typescript/testbed3d/src/Graphics.ts
new file mode 100644
index 000000000..f52d6c965
--- /dev/null
+++ b/typescript/testbed3d/src/Graphics.ts
@@ -0,0 +1,576 @@
+import * as THREE from "three";
+import {OrbitControls} from "three/examples/jsm/controls/OrbitControls";
+import RAPIER from "@dimforge/rapier3d";
+
+const BOX_INSTANCE_INDEX = 0;
+const BALL_INSTANCE_INDEX = 1;
+const CYLINDER_INSTANCE_INDEX = 2;
+const CONE_INSTANCE_INDEX = 3;
+
+var dummy = new THREE.Object3D();
+var kk = 0;
+
+interface InstanceDesc {
+ groupId: number;
+ instanceId: number;
+ elementId: number;
+ highlighted: boolean;
+ scale?: THREE.Vector3;
+}
+
+type RAPIER_API = typeof import("@dimforge/rapier3d");
+
+// NOTE: this is a very naive voxels -> mesh conversion. Proper
+// conversions should use something like greedy meshing instead.
+function genVoxelsGeometry(collider: RAPIER.Collider) {
+ // Clear the cached shape so it gets recomputed from the source of truth,
+ // and so we’ll be sure that the data contain grid coordinates even if the
+ // voxels were initialized with floating points.
+ collider.clearShapeCache();
+ let shape = collider.shape as RAPIER.Voxels;
+ let gridCoords = shape.data;
+ let sz = shape.voxelSize;
+ let vertices = [];
+ let indices = [];
+
+ let i: number;
+ for (i = 0; i < gridCoords.length; i += 3) {
+ let minx = gridCoords[i] * sz.x;
+ let miny = gridCoords[i + 1] * sz.y;
+ let minz = gridCoords[i + 2] * sz.z;
+ let maxx = minx + sz.x;
+ let maxy = miny + sz.y;
+ let maxz = minz + sz.z;
+
+ let k: number = vertices.length / 3;
+ vertices.push(minx, miny, maxz);
+ vertices.push(minx, miny, minz);
+ vertices.push(maxx, miny, minz);
+ vertices.push(maxx, miny, maxz);
+ vertices.push(minx, maxy, maxz);
+ vertices.push(minx, maxy, minz);
+ vertices.push(maxx, maxy, minz);
+ vertices.push(maxx, maxy, maxz);
+
+ indices.push(k + 4, k + 5, k + 0);
+ indices.push(k + 5, k + 1, k + 0);
+ indices.push(k + 5, k + 6, k + 1);
+ indices.push(k + 6, k + 2, k + 1);
+ indices.push(k + 6, k + 7, k + 3);
+ indices.push(k + 2, k + 6, k + 3);
+ indices.push(k + 7, k + 4, k + 0);
+ indices.push(k + 3, k + 7, k + 0);
+ indices.push(k + 0, k + 1, k + 2);
+ indices.push(k + 3, k + 0, k + 2);
+ indices.push(k + 7, k + 6, k + 5);
+ indices.push(k + 4, k + 7, k + 5);
+ }
+
+ return {
+ vertices: new Float32Array(vertices),
+ indices: new Uint32Array(indices),
+ };
+}
+
+function genHeightfieldGeometry(collider: RAPIER.Collider) {
+ let heights = collider.heightfieldHeights();
+ let nrows = collider.heightfieldNRows();
+ let ncols = collider.heightfieldNCols();
+ let scale = collider.heightfieldScale();
+
+ let vertices = [];
+ let indices = [];
+ let eltWX = 1.0 / nrows;
+ let eltWY = 1.0 / ncols;
+
+ let i: number;
+ let j: number;
+ for (j = 0; j <= ncols; ++j) {
+ for (i = 0; i <= nrows; ++i) {
+ let x = (j * eltWX - 0.5) * scale.x;
+ let y = heights[j * (nrows + 1) + i] * scale.y;
+ let z = (i * eltWY - 0.5) * scale.z;
+
+ vertices.push(x, y, z);
+ }
+ }
+
+ for (j = 0; j < ncols; ++j) {
+ for (i = 0; i < nrows; ++i) {
+ let i1 = (i + 0) * (ncols + 1) + (j + 0);
+ let i2 = (i + 0) * (ncols + 1) + (j + 1);
+ let i3 = (i + 1) * (ncols + 1) + (j + 0);
+ let i4 = (i + 1) * (ncols + 1) + (j + 1);
+
+ indices.push(i1, i3, i2);
+ indices.push(i3, i4, i2);
+ }
+ }
+
+ return {
+ vertices: new Float32Array(vertices),
+ indices: new Uint32Array(indices),
+ };
+}
+
+export class Graphics {
+ raycaster: THREE.Raycaster;
+ highlightedCollider: null | number;
+ coll2instance: Map