Skip to content

@aosengine/assets-aam

Classes

AamError

An AAM request that could not be completed.

The message names the path and the status but never the key — an error that reaches a log must not carry the credential.

Example

ts
import { AamError } from '@aosengine/assets-aam';

const err = new AamError('/api/characters/myra/ogs', 'not found', 404);
console.log(err.status, err.path); // 404 '/api/characters/myra/ogs'

Extends

  • Error

Constructors

Constructor
ts
new AamError(
   path, 
   message, 
   status?, 
   options?
): AamError;

Build an AAM error.

Parameters
ParameterTypeDescription
pathstringAAM path or URL involved.
messagestringWhat went wrong.
status?numberHTTP status, when there was one.
options?ErrorOptionsStandard Error options, used to keep the cause.
Returns

AamError

Overrides
ts
Error.constructor

Properties

path
ts
readonly path: string;

AAM path or URL the failure belongs to.

status?
ts
readonly optional status?: number;

HTTP status, when the failure came back as a response.

Interfaces

AamBundleFile

One file of a character's /ogs inference bundle.

Properties

name
ts
readonly name: string;

Bare filename, for example scene.json.

size?
ts
readonly optional size?: number;

Size in bytes, when the server reports one.

updatedAt?
ts
readonly optional updatedAt?: string;

Last-modified stamp, when the server reports one.

url
ts
readonly url: string;

Absolute URL the bytes are served from.


AamCharacterBundle

The listing of GET /api/characters/{slug}/ogs.

Properties

files
ts
readonly files: readonly AamBundleFile[];

Every file in the character's bundle, in server order.


AamCharacterEntries

What buildCharacterManifestEntries produces.

Properties

characterId
ts
readonly characterId: string;

Id of the character entry, for convenience.

entries
ts
readonly entries: readonly AssetEntry[];

The character entry plus one gltf entry per body clip.

faceClips
ts
readonly faceClips: readonly AamFaceClip[];

Face clips, which have no manifest type of their own.


AamClient

A typed AAM client bound to one deployment and one key.

Properties

baseUrl
ts
readonly baseUrl: string;

The normalised base URL, without a trailing slash.

Methods

fetchFile()
ts
fetchFile(url, options?): Promise<ArrayBuffer>;

Fetch one file's bytes, through the cache layer when it is enabled.

Parameters
ParameterTypeDescription
urlstringFile URL or AAM path.
options?AamFetchFileOptionsAbort signal and cache version token.
Returns

Promise<ArrayBuffer>

The bytes.

listAnimationAssets()
ts
listAnimationAssets(slug): Promise<AnimationAssetRow[]>;

List a character's animation clips.

Parameters
ParameterTypeDescription
slugstringCharacter slug.
Returns

Promise<AnimationAssetRow[]>

Every clip row, body and face.

listCharacterBundle()
ts
listCharacterBundle(slug): Promise<AamCharacterBundle>;

List a character's /ogs inference bundle.

Parameters
ParameterTypeDescription
slugstringCharacter slug.
Returns

Promise<AamCharacterBundle>

The bundle listing.

owns()
ts
owns(url): boolean;

Whether a URL belongs to this AAM deployment.

Parameters
ParameterTypeDescription
urlstringAbsolute URL, or a path when baseUrl is itself a path.
Returns

boolean

True when the key may be attached to it.

request()
ts
request(input, init?): Promise<Response>;

fetch with the key attached (same-origin only) and 5xx retried.

Parameters
ParameterTypeDescription
inputRequestInfo | URLURL, URL or Request to fetch.
init?RequestInitStandard fetch init; its headers are preserved.
Returns

Promise<Response>

The final Response, whatever its status.

resolveFileUrl()
ts
resolveFileUrl(path): string;

Join an AAM path onto baseUrl.

Parameters
ParameterTypeDescription
pathstringServer path such as /api/characters/myra/ogs, or a URL.
Returns

string

An absolute URL when baseUrl is absolute, else a prefixed path.


AamClientOptions

Options accepted by createAamClient.

Properties

apiKey
ts
readonly apiKey: string;

The X-API-Key value. Empty means "send no header" (cookie auth).

backoffMs?
ts
readonly optional backoffMs?: number;

First-retry delay in milliseconds; doubled on each further attempt.

baseUrl
ts
readonly baseUrl: string;

AAM origin or proxy prefix, for example https://aam.example or /aam.

cache?
ts
readonly optional cache?: AamCacheMode;

Where file bytes may be served from. Defaults to none.

fetch?
ts
readonly optional fetch?: (input, init?) => Promise<Response>;

fetch implementation. Defaults to the global one.

MDN Reference

Parameters
ParameterType
inputRequestInfo | URL
init?RequestInit
Returns

Promise<Response>

retries?
ts
readonly optional retries?: number;

Retries after the first attempt, on a network error or a 5xx.


AamEnvConfig

A usable AAM configuration read from the environment.

Properties

apiKey
ts
readonly apiKey: string;

Value of VITE_ASSET_MANAGER_API_KEY, or '' when it is unset.

Empty is legitimate: a deployment served from the same site authenticates with its session cookie, and the client then sends no X-API-Key header at all. The key is the localhost-development affordance, because a domain-scoped cookie cannot reach localhost.

baseUrl
ts
readonly baseUrl: string;

Value of VITE_ASSET_MANAGER_URL, with any trailing slash removed.


AamFaceClip

One face clip, as a JSON-serialisable record.

Face clips are ARKit weight tracks in JSON, not glTF, so they are not manifest entries — assets.json has no json type and inventing one would be a schema change. They come back as their own list instead, ready to be written into a game's own data file or handed to the animator directly.

Example

ts
import type { AamFaceClip } from '@aosengine/assets-aam';

const clip: AamFaceClip = {
  id: 'char.myra.smile',
  name: 'smile',
  url: 'https://aam.example/api/character-assets/7/smile.json',
  additive: false,
  additiveType: 'none',
  basePoseType: 'none',
  basePoseAssetId: null,
  refFrameIndex: 0,
  updatedAt: null,
};
console.log(clip.id); // 'char.myra.smile'

Properties

additive
ts
readonly additive: boolean;

Whether the clip plays as an additive layer.

additiveType
ts
readonly additiveType: AdditiveType;

Additive space.

basePoseAssetId
ts
readonly basePoseAssetId: string | null;

Row id of the clip supplying the base pose.

basePoseType
ts
readonly basePoseType: BasePoseType;

Which pose the additive bake subtracts.

id
ts
readonly id: string;

Manifest-style id, built from the same prefix as the body clips.

name
ts
readonly name: string;

The server's clip name.

refFrameIndex
ts
readonly refFrameIndex: number;

Frame index of the reference pose.

updatedAt
ts
readonly updatedAt: string | null;

Last-modified stamp, for cache versioning.

url
ts
readonly url: string;

Absolute URL the ARKit track is served from.


AamFetchFileOptions

Per-call options for AamClient.fetchFile.

Properties

signal?
ts
readonly optional signal?: AbortSignal;

Abort signal forwarded to fetch.

version?
ts
readonly optional version?: string | number | null;

Cache version token, normally the row's updatedAt or size. Changing it invalidates the Cache Storage entry, so a re-uploaded file is refetched instead of being replayed from the previous bytes.


AamResolver

A drop-in fetch bound to one AAM deployment.

Properties

fetch
ts
readonly fetch: (input, init?) => Promise<Response>;

fetch, with the key attached to AAM URLs only.

MDN Reference

Parameters
ParameterType
inputRequestInfo | URL
init?RequestInit
Returns

Promise<Response>


AnimationAssetRow

One row of GET /api/characters/{slug}/animation-assets.

The field names are the server's, not this package's: file_url is snake case and the additive settings are camel case, exactly as AAM sends them. Renaming them here would make the row un-greppable against the service.

Example

ts
import type { AnimationAssetRow } from '@aosengine/assets-aam';

const row: AnimationAssetRow = {
  id: '42',
  name: 'wave',
  kind: 'body',
  additive: true,
  file_url: '/api/character-assets/42/wave.glb',
  updatedAt: '2026-09-01T10:00:00Z',
  additiveType: 'local',
  basePoseType: 'local_frame',
  basePoseAssetId: null,
  refFrameIndex: 0,
};
console.log(row.kind); // 'body'

Properties

additive
ts
readonly additive: boolean;

Whether the clip is played as an additive layer.

additiveType
ts
readonly additiveType: AdditiveType;

Additive space. none when the clip is not additive.

basePoseAssetId
ts
readonly basePoseAssetId: string | null;

Row id of the clip supplying the base pose, for anim_frame.

basePoseType
ts
readonly basePoseType: BasePoseType;

Which pose the additive bake subtracts.

file_url
ts
readonly file_url: string;

Path or URL the bytes are served from.

id
ts
readonly id: string;

Server-assigned row id.

kind
ts
readonly kind: AnimationClipKind;

Body clip (a GLB) or face clip (an ARKit JSON track).

name
ts
readonly name: string;

Human-facing clip name; the manifest id is derived from it.

refFrameIndex
ts
readonly refFrameIndex: number;

Frame index of the reference pose inside the base clip.

updatedAt
ts
readonly updatedAt: string | null;

Last-modified stamp, used as the cache version. null when unknown.


BuildCharacterManifestOptions

Options accepted by buildCharacterManifestEntries.

Properties

idPrefix?
ts
readonly optional idPrefix?: string;

Id prefix for every entry. Defaults to char.<slug>.

rig?
ts
readonly optional rig?: AssetRig;

Rig for the character entry. Defaults to { backend: 'orl' }.

tags?
ts
readonly optional tags?: readonly string[];

Tags added to every generated entry. Defaults to ['aam', <slug>].

Type Aliases

AamCacheMode

ts
type AamCacheMode = "none" | "cache-storage";

Where AamClient.fetchFile may serve bytes from.


AdditiveType

ts
type AdditiveType = "none" | "local" | "mesh";

Which pose space an additive clip was baked in.


AnimationClipKind

ts
type AnimationClipKind = "body" | "face";

Whether a clip drives the body rig or the face.


BasePoseType

ts
type BasePoseType = "none" | "local_frame" | "anim_frame" | "ref_pose";

Which pose an additive clip subtracts to become a delta.

Variables

PACKAGE

ts
const PACKAGE: "@aosengine/assets-aam";

Package identity marker.

Example

ts
import { PACKAGE } from '@aosengine/assets-aam';

console.log(PACKAGE); // '@aosengine/assets-aam'

Functions

aamConfigFromEnv()

ts
function aamConfigFromEnv(env?): AamEnvConfig | null;

Read the AAM configuration from a Vite-style environment.

Parameters

ParameterTypeDescription
envRecord<string, string | undefined>Environment record. Defaults to import.meta.env.

Returns

AamEnvConfig | null

The configuration, or null when VITE_ASSET_MANAGER_URL is unset or blank — which means the adapter is simply not in use.

Example

ts
import { aamConfigFromEnv, createAamClient } from '@aosengine/assets-aam';

const config = aamConfigFromEnv({ VITE_ASSET_MANAGER_URL: 'https://aam.example' });
const client = config === null ? null : createAamClient(config);
console.log(config?.baseUrl); // 'https://aam.example'

buildCharacterManifestEntries()

ts
function buildCharacterManifestEntries(
   client, 
   slug, 
   options?
): Promise<AamCharacterEntries>;

Read a character's listings and turn them into manifest entries.

The character entry's src is a virtual directory URL<baseUrl>/api/characters/<slug>/ogs/ — not a single file. The character loader appends a filename to it (scene.json, mesh.json, the decoders) and fetches each one, exactly as it would from a static directory; the only difference is that the directory is served by AAM and needs the key, which is what createAamResolver supplies.

The bundle listing is fetched as well as the directory being named, so an empty or missing bundle fails here, with the character's slug in the message, rather than deep inside the loader on a 404 for scene.json.

Parameters

ParameterTypeDescription
clientAamClientClient for the deployment the character lives in.
slugstringCharacter slug.
optionsBuildCharacterManifestOptionsId prefix, rig and tags.

Returns

Promise<AamCharacterEntries>

The character entry, the body-clip entries and the face clips.

Example

ts
import { buildCharacterManifestEntries, createAamClient } from '@aosengine/assets-aam';

const client = createAamClient({ baseUrl: 'https://aam.example', apiKey: key });
const built = await buildCharacterManifestEntries(client, 'myra');
console.log(built.characterId); // 'char.myra'

createAamClient()

ts
function createAamClient(options): AamClient;

Build a client for one AAM deployment.

Parameters

ParameterTypeDescription
optionsAamClientOptionsBase URL, key, and the injectable fetch, retry and cache policy.

Returns

AamClient

The client.

Example

ts
import { createAamClient } from '@aosengine/assets-aam';

const client = createAamClient({ baseUrl: 'https://aam.example', apiKey: key });
console.log(client.resolveFileUrl('/api/characters/myra/ogs'));
// 'https://aam.example/api/characters/myra/ogs'

createAamResolver()

ts
function createAamResolver(client): AamResolver;

Build the fetch option for loadManifest and loadCharacterBundle.

Parameters

ParameterTypeDescription
clientAamClientClient for the deployment that holds the key.

Returns

AamResolver

An object with a single fetch, assignable anywhere the engine accepts a fetch override.

Example

ts
import { loadManifest } from '@aosengine/assets';
import { createAamClient, createAamResolver } from '@aosengine/assets-aam';

const client = createAamClient({ baseUrl: 'https://aam.example', apiKey: key });
const resolver = createAamResolver(client);
const manifest = await loadManifest('/assets/assets.json', { fetch: resolver.fetch });
console.log(manifest.assets.length);

mergeManifests()

ts
function mergeManifests(base, extra): AssetManifest;

Merge generated entries into a game's manifest.

Entries built by buildCharacterManifestEntries carry absolute URLs, so the base manifest's baseUrl does not apply to them and is preserved untouched for everything that was already there. A duplicate id throws: an id is the guest/host contract, and silently letting one definition win would change what a running game loads without changing a line of its code.

Parameters

ParameterTypeDescription
baseAssetManifestThe game's manifest.
extra| AssetManifest | readonly AssetEntry[]Entries to add, or another manifest to take entries from.

Returns

AssetManifest

A new frozen manifest.

Example

ts
import { parseManifest } from '@aosengine/assets';
import { mergeManifests } from '@aosengine/assets-aam';

const base = parseManifest({ version: 1, baseUrl: '/assets/', assets: [] });
const merged = mergeManifests(base, [
  { id: 'char.myra.wave', type: 'gltf', src: 'https://aam.example/f/wave.glb' },
]);
console.log(merged.assets.length); // 1