How to use Rapier in TypeScript?

The Rapier physics engine written in Rust is exposed to JavaScript by loading the library into a module dynamically. From Getting started:

import('@dimforge/rapier2d').then(RAPIER => {
    ...
});

I need to use the Rapier module to instantiate vectors from outside code from TypeScript and Node.js with ts-node. I'm not sure if the properties matter much since it's all dynamically-typed and TypeScript does structural type checks also, but when invoking new rapier.Vector it could matter.

I created a convenient layer over Rapier's JavaScript bindings (com.hydroper.matter) which uses this internally, leaving their dynamic module at the static lifetime of the JavaScript program:

import * as rapierTypings from "@dimforge/rapier2d/rapier";
import Vector from "../math/Vector";
import { RigidBodyType } from "../RigidBody";

const Rapier = {
    rapier: undefined as (typeof import("@dimforge/rapier2d/rapier") | undefined),

    get(): typeof import("@dimforge/rapier2d/rapier") {
        if (Rapier.rapier === undefined) {
            throw new Error("com.hydroper.matter must be preloaded before use; do so through the asynchronous load() method.");
        }
        return Rapier.rapier;
    },

    ...
};

Now... ts-node is reporting the following issue when I run my terminal application that uses Rapier indirectly:

Error: Cannot find module '@dimforge/rapier2d'
Require stack:
- /fooProject/matter/ts/index.ts
- /fooProject/fooProject-server/ts/car/Car.ts
- /fooProject/fooProject-server/ts/Peer.ts
- /fooProject/fooProject-server/ts/index.ts
- /fooProject/fooProject-server/bin/fooProject-server
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:1077:15)
    at Function.Module._resolveFilename.sharedData.moduleResolveFilenameHook.installedValue [as _resolveFilename] (/fooProject/fooProject-server/node_modules/@cspotcode/source-map-support/source-map-support.js:811:30)
    at Function.Module._load (node:internal/modules/cjs/loader:922:27)
    at Module.require (node:internal/modules/cjs/loader:1143:19)
    at require (node:internal/modules/cjs/helpers:110:18)
    at /fooProject/matter/ts/index.ts:47:21 {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/fooProject/matter/ts/index.ts',
    '/fooProject/fooProject-server/ts/car/Car.ts',
    '/fooProject/fooProject-server/ts/Peer.ts',
    '/fooProject/fooProject-server/ts/index.ts',
    '/fooProject/fooProject-server/bin/fooProject-server'
  ]
}

Relevant code from index.ts:

export async function load(): Promise<void> {
    if (Rapier.rapier !== undefined) {
        return;
    }
    Rapier.rapier = await import("@dimforge/rapier2d");
}

The error is on this import specifically...

What do you mean by using it indirectly?

Basically this:

fooProject-server/ts/index.ts:

import * as matter from "com.hydroper.matter";

class Server {
    ...

    private async run(port: number) {
        // Load the physics library
        await matter.load();

        ...
    }

    ...
}

Then I can use some customized API of mine to access a statically-assigned Rapier module.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.