# `testing.manifestFromGlb`

> Contract 2.0.0 · package sha256 `a857eca95b35921109faf997094bb4192f12527d9d0fcd4be7e97f06425bad6e` · generated from `testing.d.ts` by `services/onsite-scripter/scripts/build-contract-docs.mjs`; edit the source, not this file.

Function · `import { manifestFromGlb } from '@holostep-configurators/runtime-client/testing';` · labs, `@experimental` · since 2.0.0 · section 24. /testing

A GLB's manifest, read with no browser and no engine (Node 20 or later, or a page), for an
author with a file and no human: its parts, slots, connector planes, size, clips and variants,
for [`checkAsset`](checkAsset.md) (the root's), the fake (`fakeModelFromGlb`) and its own rules. It is in
`/testing`, the entry a Node script or test installs, not the root: an app's page never reads
a GLB. A stamped GLB answers its stamped manifest (`asset.extras.holostep.manifest`) as
written. An unstamped one is measured as
the stamper measures it (spec section 7.1) and as the runtime reads the file: parts in the
scene's pre-order walk, ids `extras.holostep.id` else the cleaned name (`_<n>` when taken, counted
in that walk); `dimsM` and `origin` from the meshes' POSITION bounds under their node matrices,
connector planes excluded; connector planes (a one-primitive mesh stamped
`extras.holostep.connector`, or named with a 1.4 prefix: 'snap_plane', 'magnetic_plane',
'mp_', 'mp-') with their centre, normal and hull read from their vertices as the runtime reads
them, their `type` from the stamp, else the first `_` segment after the prefix, else 'default'.
A plane whose vertices are compressed (Draco, meshopt) is read from its POSITION bounds: the
box's thinnest axis, positive, is its normal. `front` is 'other' unless the GLB says '-Z';
`provenance` is `stampedBy: 'other'` with the file's sha256. [`describe(node).manifest`](ModelDescription.manifest.md) stays null
for an unstamped GLB: this reads the file, it stamps nothing.
Errors: rejects HoloInputError ('invalid-input', path 'glb') when the bytes are no glTF 2.0
binary (no 'glTF' magic, another version, no JSON chunk).

## Declaration

```ts
export function manifestFromGlb(glb: ArrayBuffer | Uint8Array, options?: ManifestFromGlbOptions): Promise<AssetManifest>;
```

## Example

Imports: values (`has`, `validate`, the `Holo*Error` classes, the pure helpers) from `@holostep-configurators/runtime-client`, types from `@holostep-configurators/runtime-client/contract`, `/math` and `/testing` names from those entries; `boot` from the runtime module the root's `loadRuntimeAtFloor` resolves to. A type your page defines is your app's: declare it there, never import it from the package.

Compiled under the contract's strict settings (`examples/declaration/24-manifestFromGlb.ts`):

```ts
import { checkAsset } from '@holostep-configurators/runtime-client';
import { manifestFromGlb } from '@holostep-configurators/runtime-client/testing';
import type { Session } from '@holostep-configurators/runtime-client/contract';
declare const session: Session;
declare const signal: AbortSignal;
declare const glb: Uint8Array; // the file's bytes: in Node, await readFile('kozepso_60.glb')
const manifest = await manifestFromGlb(glb, { fileName: 'kozepso_60.glb' });
const checked = checkAsset(manifest, { connectors: [{ type: 'left' }] });
for (const issue of checked.failures) console.warn(issue.code, issue.message);
console.info(manifest.dimsM, manifest.parts.map((p) => p.id), manifest.animations);
```

## Generic-API test (spec 3.1)

| Rule | Result |
| --- | --- |
| 1. Neutral name | pass: `manifestFromGlb` names no product |
| 2. A precedent | not recorded: no ledger row (coverage.json) names this member or its owner |
| 3. Two apps, or labs | labs (`@experimental` at a stable path, reached through `has()` or `supports()`): it graduates when a second app uses it |
| 4. The cheaper fix first | not recorded per member (Appendix B decides it per need) |
