libassimp
0.1.0

Resolve sidecar files

Load referenced buffers, textures, materials, and layers asynchronously when Assimp asks for them.

Open Markdown

resolve(name) may return bytes, undefined, or a Promise of either. Supplied files are checked first; the resolver handles names not already present.

Fetch over the network

import { convert } from 'libassimp';const entryUrl = new URL('https://assets.example/scene.gltf');const entry = await fetch(entryUrl);const bytes = new Uint8Array(await entry.arrayBuffer());const { files } = await convert(  { name: 'scene.gltf', bytes },  {    to: 'glb',    resolve: async (name) => {      const response = await fetch(new URL(name, entryUrl));      return response.ok ? new Uint8Array(await response.arrayBuffer()) : undefined;    },  },);console.log(files[0].name);

Input

objcube.obj165 B
mtlcube.mtl55 B

Output

Preparing artifact…

Convert
Output
Files
WASM load

Returning undefined means unavailable; Assimp decides whether that reference is optional. Throwing or rejecting produces RESOLVE_FAILED with the exact fileName and original cause.

Read from Node asynchronously

import { convert } from 'libassimp';
import { readFile } from 'node:fs/promises';
import { isAbsolute, relative, resolve, sep } from 'node:path';

const modelsRoot = resolve('models');
const bytes = new Uint8Array(await readFile(resolve(modelsRoot, 'cube.obj')));
const { files } = await convert(
  { name: 'cube.obj', bytes },
  {
    to: 'glb',
    resolve: async (name) => {
      const candidate = resolve(modelsRoot, name);
      const relativePath = relative(modelsRoot, candidate);
      if (relativePath === '..' || relativePath.startsWith(`..${sep}`) || isAbsolute(relativePath)) {
        return undefined;
      }
      try {
        return new Uint8Array(await readFile(candidate));
      } catch {
        return undefined;
      }
    },
  },
);

console.log(files[0].name);

The consumer callback is invoked once per exact requested name within a conversion. JSPI hosts suspend inside parsing; other hosts transparently replay staged parsing from the settled per-call cache. The public behavior is identical.

Browser-picked files

Files already selected together are simplest as the input array. A directory picker can also populate a Map<string, Uint8Array> and return map.get(name) synchronously. No prefetch is required for sources that support async reads.

On this page