@forgeax/engine-assets-runtime 0.1.3 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +442 -175
- package/dist/.tsbuildinfo +1 -1
- package/dist/__tests__/aabb.unit.test.d.ts +2 -0
- package/dist/__tests__/aabb.unit.test.d.ts.map +1 -0
- package/dist/__tests__/artifact-integrity.unit.test.d.ts +2 -0
- package/dist/__tests__/artifact-integrity.unit.test.d.ts.map +1 -0
- package/dist/__tests__/artifact-io.unit.test.d.ts +2 -0
- package/dist/__tests__/artifact-io.unit.test.d.ts.map +1 -0
- package/dist/__tests__/asset-evidence-sdk.integration.test.d.ts +2 -0
- package/dist/__tests__/asset-evidence-sdk.integration.test.d.ts.map +1 -0
- package/dist/__tests__/asset-evidence.unit.test.d.ts +2 -0
- package/dist/__tests__/asset-evidence.unit.test.d.ts.map +1 -0
- package/dist/__tests__/asset-kind.unit.test.d.ts +2 -0
- package/dist/__tests__/asset-kind.unit.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry-catalog-reconcile.integration.test.d.ts +2 -0
- package/dist/__tests__/asset-registry-catalog-reconcile.integration.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry-catalog-reconcile.unit.test.d.ts +2 -0
- package/dist/__tests__/asset-registry-catalog-reconcile.unit.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry-catalog.unit.test.d.ts +2 -0
- package/dist/__tests__/asset-registry-catalog.unit.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry.pack-cache.test.d.ts +2 -0
- package/dist/__tests__/asset-registry.pack-cache.test.d.ts.map +1 -0
- package/dist/__tests__/asset-registry.unit.test.d.ts +2 -0
- package/dist/__tests__/asset-registry.unit.test.d.ts.map +1 -0
- package/dist/__tests__/asset-runtime-error-code-owner.test-d.d.ts +2 -0
- package/dist/__tests__/asset-runtime-error-code-owner.test-d.d.ts.map +1 -0
- package/dist/__tests__/catalog-replica.unit.test.d.ts +2 -0
- package/dist/__tests__/catalog-replica.unit.test.d.ts.map +1 -0
- package/dist/__tests__/catalog-source-v2.unit.test.d.ts +2 -0
- package/dist/__tests__/catalog-source-v2.unit.test.d.ts.map +1 -0
- package/dist/__tests__/catalog-source.unit.test.d.ts +2 -0
- package/dist/__tests__/catalog-source.unit.test.d.ts.map +1 -0
- package/dist/__tests__/catalog-subscription-order.unit.test.d.ts +2 -0
- package/dist/__tests__/catalog-subscription-order.unit.test.d.ts.map +1 -0
- package/dist/__tests__/catalog-subscription.unit.test.d.ts +2 -0
- package/dist/__tests__/catalog-subscription.unit.test.d.ts.map +1 -0
- package/dist/__tests__/decode-image-bytes-pass-through.test.d.ts +2 -0
- package/dist/__tests__/decode-image-bytes-pass-through.test.d.ts.map +1 -0
- package/dist/__tests__/decode-image-bytes.browser.test.d.ts +2 -0
- package/dist/__tests__/decode-image-bytes.browser.test.d.ts.map +1 -0
- package/dist/__tests__/decode-image-bytes.test-d.d.ts +2 -0
- package/dist/__tests__/decode-image-bytes.test-d.d.ts.map +1 -0
- package/dist/__tests__/decode-image-bytes.test.d.ts +2 -0
- package/dist/__tests__/decode-image-bytes.test.d.ts.map +1 -0
- package/dist/__tests__/dynamic-texture-store.unit.test.d.ts +2 -0
- package/dist/__tests__/dynamic-texture-store.unit.test.d.ts.map +1 -0
- package/dist/__tests__/errors-asset.unit.test.d.ts +2 -0
- package/dist/__tests__/errors-asset.unit.test.d.ts.map +1 -0
- package/dist/__tests__/inline-pack-loaders.unit.test.d.ts +2 -0
- package/dist/__tests__/inline-pack-loaders.unit.test.d.ts.map +1 -0
- package/dist/__tests__/instantiate-context.unit.test.d.ts +2 -0
- package/dist/__tests__/instantiate-context.unit.test.d.ts.map +1 -0
- package/dist/__tests__/instantiate-publication-fence.unit.test.d.ts +2 -0
- package/dist/__tests__/instantiate-publication-fence.unit.test.d.ts.map +1 -0
- package/dist/__tests__/instantiate.unit.test.d.ts +2 -0
- package/dist/__tests__/instantiate.unit.test.d.ts.map +1 -0
- package/dist/__tests__/loader-input-contract.unit.test.d.ts +2 -0
- package/dist/__tests__/loader-input-contract.unit.test.d.ts.map +1 -0
- package/dist/__tests__/loader-registry.unit.test.d.ts +2 -0
- package/dist/__tests__/loader-registry.unit.test.d.ts.map +1 -0
- package/dist/__tests__/material-dependency-invalidation.unit.test.d.ts +2 -0
- package/dist/__tests__/material-dependency-invalidation.unit.test.d.ts.map +1 -0
- package/dist/__tests__/material-generation-cache.unit.test.d.ts +2 -0
- package/dist/__tests__/material-generation-cache.unit.test.d.ts.map +1 -0
- package/dist/__tests__/material-load-consumer.test-d.d.ts +2 -0
- package/dist/__tests__/material-load-consumer.test-d.d.ts.map +1 -0
- package/dist/__tests__/material-ready.integration.test.d.ts +2 -0
- package/dist/__tests__/material-ready.integration.test.d.ts.map +1 -0
- package/dist/__tests__/material-stale-generation.unit.test.d.ts +2 -0
- package/dist/__tests__/material-stale-generation.unit.test.d.ts.map +1 -0
- package/dist/__tests__/mesh-bin-morph-v3.test.d.ts +2 -0
- package/dist/__tests__/mesh-bin-morph-v3.test.d.ts.map +1 -0
- package/dist/__tests__/mesh-bin.unit.test.d.ts +2 -0
- package/dist/__tests__/mesh-bin.unit.test.d.ts.map +1 -0
- package/dist/__tests__/mipmap-generator.unit.test.d.ts +2 -0
- package/dist/__tests__/mipmap-generator.unit.test.d.ts.map +1 -0
- package/dist/__tests__/pack-artifact-transcode-model-owner.test.d.ts +2 -0
- package/dist/__tests__/pack-artifact-transcode-model-owner.test.d.ts.map +1 -0
- package/dist/__tests__/pack-basis-load.integration.test.d.ts +2 -0
- package/dist/__tests__/pack-basis-load.integration.test.d.ts.map +1 -0
- package/dist/__tests__/payload-validate.unit.test.d.ts +2 -0
- package/dist/__tests__/payload-validate.unit.test.d.ts.map +1 -0
- package/dist/__tests__/plugin.test.d.ts +2 -0
- package/dist/__tests__/plugin.test.d.ts.map +1 -0
- package/dist/__tests__/registry-concurrency.bench.test.d.ts +2 -0
- package/dist/__tests__/registry-concurrency.bench.test.d.ts.map +1 -0
- package/dist/__tests__/registry-failure-retry.integration.test.d.ts +2 -0
- package/dist/__tests__/registry-failure-retry.integration.test.d.ts.map +1 -0
- package/dist/__tests__/registry-load-graph.integration.test.d.ts +2 -0
- package/dist/__tests__/registry-load-graph.integration.test.d.ts.map +1 -0
- package/dist/__tests__/registry-load-state.unit.test.d.ts +2 -0
- package/dist/__tests__/registry-load-state.unit.test.d.ts.map +1 -0
- package/dist/__tests__/registry-package-cache.unit.test.d.ts +2 -0
- package/dist/__tests__/registry-package-cache.unit.test.d.ts.map +1 -0
- package/dist/__tests__/registry-public-ready.unit.test.d.ts +2 -0
- package/dist/__tests__/registry-public-ready.unit.test.d.ts.map +1 -0
- package/dist/__tests__/resolve-asset-handle.unit.test.d.ts +2 -0
- package/dist/__tests__/resolve-asset-handle.unit.test.d.ts.map +1 -0
- package/dist/__tests__/scene-handle-fields.unit.test.d.ts +2 -0
- package/dist/__tests__/scene-handle-fields.unit.test.d.ts.map +1 -0
- package/dist/__tests__/scene-payload.unit.test.d.ts +2 -0
- package/dist/__tests__/scene-payload.unit.test.d.ts.map +1 -0
- package/dist/__tests__/scene-publication-fence.test.d.ts +2 -0
- package/dist/__tests__/scene-publication-fence.test.d.ts.map +1 -0
- package/dist/__tests__/scriptable-pack-public-surface.test-d.d.ts +2 -0
- package/dist/__tests__/scriptable-pack-public-surface.test-d.d.ts.map +1 -0
- package/dist/__tests__/static-rig.integration.test.d.ts +2 -0
- package/dist/__tests__/static-rig.integration.test.d.ts.map +1 -0
- package/dist/__tests__/validate-material.unit.test.d.ts +2 -0
- package/dist/__tests__/validate-material.unit.test.d.ts.map +1 -0
- package/dist/__tests__/video-pack-loader.integration.test.d.ts +2 -0
- package/dist/__tests__/video-pack-loader.integration.test.d.ts.map +1 -0
- package/dist/aabb.d.ts +3 -0
- package/dist/aabb.d.ts.map +1 -0
- package/dist/asset-registry.d.ts +552 -0
- package/dist/asset-registry.d.ts.map +1 -0
- package/dist/builtin-asset-registry.d.ts +22 -0
- package/dist/builtin-asset-registry.d.ts.map +1 -0
- package/dist/catalog-source.d.ts +2 -1
- package/dist/catalog-source.d.ts.map +1 -1
- package/dist/decode-image-bytes.d.ts +57 -0
- package/dist/decode-image-bytes.d.ts.map +1 -0
- package/dist/dynamic-texture-store.d.ts +89 -0
- package/dist/dynamic-texture-store.d.ts.map +1 -0
- package/dist/errors/asset.d.ts +201 -0
- package/dist/errors/asset.d.ts.map +1 -0
- package/dist/handles.d.ts +141 -0
- package/dist/handles.d.ts.map +1 -0
- package/dist/image-error.d.ts +6 -0
- package/dist/image-error.d.ts.map +1 -0
- package/dist/index.d.ts +32 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +7218 -114
- package/dist/index.mjs.map +1 -1
- package/dist/internal.d.ts +2 -1
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.mjs +317 -3
- package/dist/internal.mjs.map +1 -1
- package/dist/loader-registry.d.ts +63 -0
- package/dist/loader-registry.d.ts.map +1 -0
- package/dist/loaders/inline-pack.d.ts +72 -0
- package/dist/loaders/inline-pack.d.ts.map +1 -0
- package/dist/loaders/mesh-bin.d.ts +21 -0
- package/dist/loaders/mesh-bin.d.ts.map +1 -0
- package/dist/loaders/pack-artifact.d.ts +20 -0
- package/dist/loaders/pack-artifact.d.ts.map +1 -0
- package/dist/material/dependency-graph.d.ts +9 -0
- package/dist/material/dependency-graph.d.ts.map +1 -0
- package/dist/material/generation-cache.d.ts +24 -0
- package/dist/material/generation-cache.d.ts.map +1 -0
- package/dist/material/inspection.d.ts +24 -0
- package/dist/material/inspection.d.ts.map +1 -0
- package/dist/material/loader.d.ts +59 -0
- package/dist/material/loader.d.ts.map +1 -0
- package/dist/material/runtime-shader.d.ts +14 -0
- package/dist/material/runtime-shader.d.ts.map +1 -0
- package/dist/mesh-bin.d.ts +3 -0
- package/dist/mesh-bin.d.ts.map +1 -0
- package/dist/mipmap-generator.d.ts +132 -0
- package/dist/mipmap-generator.d.ts.map +1 -0
- package/dist/payload-validate.d.ts +60 -0
- package/dist/payload-validate.d.ts.map +1 -0
- package/dist/plugin.d.ts +16 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/registry/artifact-io.d.ts +16 -0
- package/dist/registry/artifact-io.d.ts.map +1 -0
- package/dist/registry/asset-evidence.d.ts +13 -0
- package/dist/registry/asset-evidence.d.ts.map +1 -0
- package/dist/registry/catalog-state.d.ts +47 -0
- package/dist/registry/catalog-state.d.ts.map +1 -0
- package/dist/registry/catalog.d.ts +48 -0
- package/dist/registry/catalog.d.ts.map +1 -0
- package/dist/registry/instantiate.d.ts +153 -0
- package/dist/registry/instantiate.d.ts.map +1 -0
- package/dist/registry/load-by-guid.d.ts +247 -0
- package/dist/registry/load-by-guid.d.ts.map +1 -0
- package/dist/registry/load-state.d.ts +26 -0
- package/dist/registry/load-state.d.ts.map +1 -0
- package/dist/registry/runtime-projection.d.ts +16 -0
- package/dist/registry/runtime-projection.d.ts.map +1 -0
- package/dist/registry/scene-publication-fence.d.ts +38 -0
- package/dist/registry/scene-publication-fence.d.ts.map +1 -0
- package/dist/registry/validate-material.d.ts +77 -0
- package/dist/registry/validate-material.d.ts.map +1 -0
- package/dist/resolve-asset-handle.d.ts +43 -0
- package/dist/resolve-asset-handle.d.ts.map +1 -0
- package/dist/resolve-tileset-runtime.d.ts +23 -0
- package/dist/resolve-tileset-runtime.d.ts.map +1 -0
- package/dist/scene-handle-fields.d.ts +88 -0
- package/dist/scene-handle-fields.d.ts.map +1 -0
- package/dist/scene-payload.d.ts +15 -0
- package/dist/scene-payload.d.ts.map +1 -0
- package/dist/wire-default-loaders.d.ts +29 -0
- package/dist/wire-default-loaders.d.ts.map +1 -0
- package/package.json +22 -9
- package/src/__tests__/aabb.unit.test.ts +97 -0
- package/src/__tests__/artifact-integrity.unit.test.ts +99 -0
- package/src/__tests__/artifact-io.unit.test.ts +127 -0
- package/src/__tests__/asset-evidence-sdk.integration.test.ts +32 -0
- package/src/__tests__/asset-evidence.unit.test.ts +32 -0
- package/src/__tests__/{asset-kind.test.ts → asset-kind.unit.test.ts} +1 -1
- package/src/__tests__/asset-registry-catalog-reconcile.integration.test.ts +74 -0
- package/src/__tests__/asset-registry-catalog-reconcile.unit.test.ts +89 -0
- package/src/__tests__/asset-registry-catalog.unit.test.ts +170 -0
- package/src/__tests__/asset-registry.pack-cache.test.ts +96 -0
- package/src/__tests__/asset-registry.unit.test.ts +511 -0
- package/src/__tests__/asset-runtime-error-code-owner.test-d.ts +63 -0
- package/src/__tests__/catalog-replica.unit.test.ts +196 -0
- package/src/__tests__/catalog-source-v2.unit.test.ts +158 -0
- package/src/__tests__/catalog-source.unit.test.ts +126 -0
- package/src/__tests__/catalog-subscription-order.unit.test.ts +65 -0
- package/src/__tests__/catalog-subscription.unit.test.ts +28 -0
- package/src/__tests__/decode-image-bytes-pass-through.test.ts +34 -0
- package/src/__tests__/decode-image-bytes.browser.test.ts +102 -0
- package/src/__tests__/decode-image-bytes.test-d.ts +108 -0
- package/src/__tests__/decode-image-bytes.test.ts +90 -0
- package/src/__tests__/decode-image-mime-owner.test.ts +2 -5
- package/src/__tests__/dynamic-texture-store.unit.test.ts +115 -0
- package/src/__tests__/errors-asset.unit.test.ts +92 -0
- package/src/__tests__/inline-pack-loaders.unit.test.ts +548 -0
- package/src/__tests__/instantiate-context.unit.test.ts +65 -0
- package/src/__tests__/instantiate-publication-fence.unit.test.ts +158 -0
- package/src/__tests__/instantiate.unit.test.ts +684 -0
- package/src/__tests__/loader-input-contract.unit.test.ts +89 -0
- package/src/__tests__/loader-registry.unit.test.ts +101 -0
- package/src/__tests__/material-dependency-invalidation.unit.test.ts +14 -0
- package/src/__tests__/material-generation-cache.unit.test.ts +46 -0
- package/src/__tests__/material-load-consumer.test-d.ts +42 -0
- package/src/__tests__/material-ready.integration.test.ts +492 -0
- package/src/__tests__/material-stale-generation.unit.test.ts +152 -0
- package/src/__tests__/mesh-bin-morph-v3.test.ts +22 -0
- package/src/__tests__/mesh-bin.unit.test.ts +152 -0
- package/src/__tests__/mipmap-generator.unit.test.ts +202 -0
- package/src/__tests__/pack-artifact-transcode-model-owner.test.ts +32 -0
- package/src/__tests__/pack-basis-load.integration.test.ts +168 -0
- package/src/__tests__/payload-validate.unit.test.ts +285 -0
- package/src/__tests__/plugin.test.ts +55 -0
- package/src/__tests__/registry-concurrency.bench.test.ts +40 -0
- package/src/__tests__/registry-failure-retry.integration.test.ts +69 -0
- package/src/__tests__/registry-load-graph.integration.test.ts +246 -0
- package/src/__tests__/registry-load-state.unit.test.ts +35 -0
- package/src/__tests__/registry-package-cache.unit.test.ts +53 -0
- package/src/__tests__/registry-public-ready.unit.test.ts +38 -0
- package/src/__tests__/resolve-asset-handle.unit.test.ts +238 -0
- package/src/__tests__/scene-handle-fields.unit.test.ts +129 -0
- package/src/__tests__/scene-payload.unit.test.ts +151 -0
- package/src/__tests__/scene-publication-fence.test.ts +129 -0
- package/src/__tests__/scriptable-pack-public-surface.test-d.ts +16 -0
- package/src/__tests__/static-rig.integration.test.ts +8 -0
- package/src/__tests__/validate-material.unit.test.ts +359 -0
- package/src/__tests__/video-pack-loader.integration.test.ts +83 -0
- package/src/aabb.ts +107 -0
- package/src/asset-registry.ts +2040 -0
- package/src/builtin-asset-registry.ts +164 -0
- package/src/catalog-source.ts +14 -70
- package/src/decode-image-bytes.ts +126 -0
- package/src/dynamic-texture-store.ts +234 -0
- package/src/errors/asset.ts +347 -0
- package/src/handles.ts +180 -0
- package/src/image-error.ts +45 -0
- package/src/index.ts +177 -19
- package/src/internal.ts +2 -0
- package/src/loader-registry.ts +157 -0
- package/src/loaders/inline-pack.ts +837 -0
- package/src/loaders/mesh-bin.ts +304 -0
- package/src/loaders/pack-artifact.ts +665 -0
- package/src/material/dependency-graph.ts +46 -0
- package/src/material/generation-cache.ts +177 -0
- package/src/material/inspection.ts +46 -0
- package/src/material/loader.ts +326 -0
- package/src/material/runtime-shader.ts +133 -0
- package/src/mesh-bin.ts +5 -0
- package/src/mipmap-generator.ts +450 -0
- package/src/payload-validate.ts +573 -0
- package/src/plugin.ts +48 -0
- package/src/registry/artifact-io.ts +259 -0
- package/src/registry/asset-evidence.ts +51 -0
- package/src/registry/catalog-state.ts +409 -0
- package/src/registry/catalog.ts +369 -0
- package/src/registry/instantiate.ts +1056 -0
- package/src/registry/load-by-guid.ts +1657 -0
- package/src/registry/load-state.ts +115 -0
- package/src/registry/runtime-projection.ts +63 -0
- package/src/registry/scene-publication-fence.ts +256 -0
- package/src/registry/validate-material.ts +386 -0
- package/src/resolve-asset-handle.ts +147 -0
- package/src/resolve-tileset-runtime.ts +72 -0
- package/src/scene-handle-fields.ts +221 -0
- package/src/scene-payload.ts +207 -0
- package/src/wire-default-loaders.ts +79 -0
- package/dist/__tests__/asset-graph-red.integration.test.d.ts +0 -2
- package/dist/__tests__/asset-graph-red.integration.test.d.ts.map +0 -1
- package/dist/__tests__/asset-kind.test.d.ts +0 -2
- package/dist/__tests__/asset-kind.test.d.ts.map +0 -1
- package/dist/__tests__/asset-registry-core.integration.test.d.ts +0 -2
- package/dist/__tests__/asset-registry-core.integration.test.d.ts.map +0 -1
- package/dist/__tests__/asset-registry-public-api.test-d.d.ts +0 -2
- package/dist/__tests__/asset-registry-public-api.test-d.d.ts.map +0 -1
- package/dist/__tests__/asset-runtime-core-lifecycle.integration.test.d.ts +0 -2
- package/dist/__tests__/asset-runtime-core-lifecycle.integration.test.d.ts.map +0 -1
- package/dist/__tests__/asset-runtime-snapshot.unit.test.d.ts +0 -2
- package/dist/__tests__/asset-runtime-snapshot.unit.test.d.ts.map +0 -1
- package/dist/__tests__/catalog-session-red.unit.test.d.ts +0 -2
- package/dist/__tests__/catalog-session-red.unit.test.d.ts.map +0 -1
- package/dist/__tests__/registry-lifecycle-red.integration.test.d.ts +0 -2
- package/dist/__tests__/registry-lifecycle-red.integration.test.d.ts.map +0 -1
- package/src/__tests__/asset-graph-red.integration.test.ts +0 -113
- package/src/__tests__/asset-registry-core.integration.test.ts +0 -161
- package/src/__tests__/asset-registry-public-api.test-d.ts +0 -31
- package/src/__tests__/asset-runtime-core-lifecycle.integration.test.ts +0 -79
- package/src/__tests__/asset-runtime-snapshot.unit.test.ts +0 -23
- package/src/__tests__/catalog-session-red.unit.test.ts +0 -276
- package/src/__tests__/registry-lifecycle-red.integration.test.ts +0 -80
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { World } from '@forgeax/engine-ecs';
|
|
2
|
+
import type { Asset, Handle, Result, TextureAsset } from '@forgeax/engine-types';
|
|
3
|
+
export type TilesetRuntimeErrorCode = 'tileset-atlas-not-found' | 'tileset-atlas-stale' | 'tileset-atlas-kind-mismatch';
|
|
4
|
+
export interface TilesetRuntimeError {
|
|
5
|
+
readonly code: TilesetRuntimeErrorCode;
|
|
6
|
+
readonly expected: string;
|
|
7
|
+
readonly hint: string;
|
|
8
|
+
readonly detail: {
|
|
9
|
+
readonly guid: string;
|
|
10
|
+
readonly actualKind?: string;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export interface ResolvedTilesetRuntime {
|
|
14
|
+
readonly guid: string;
|
|
15
|
+
readonly payload: TextureAsset;
|
|
16
|
+
readonly handle: Handle<'TextureAsset', 'shared'>;
|
|
17
|
+
}
|
|
18
|
+
export type TilesetAtlasLookup = Asset | {
|
|
19
|
+
readonly code: 'stale';
|
|
20
|
+
} | undefined;
|
|
21
|
+
/** Project one durable atlas GUID into the current World at the tilemap owner. */
|
|
22
|
+
export declare function resolveTilesetRuntime(world: World, guid: string, lookup: (guid: string) => TilesetAtlasLookup): Result<ResolvedTilesetRuntime, TilesetRuntimeError>;
|
|
23
|
+
//# sourceMappingURL=resolve-tileset-runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-tileset-runtime.d.ts","sourceRoot":"","sources":["../src/resolve-tileset-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAGjF,MAAM,MAAM,uBAAuB,GAC/B,yBAAyB,GACzB,qBAAqB,GACrB,6BAA6B,CAAC;AAElC,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,uBAAuB,CAAC;IACvC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE;QACf,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;KAC9B,CAAC;CACH;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;CACnD;AAED,MAAM,MAAM,kBAAkB,GAAG,KAAK,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,CAAC;AAEhF,kFAAkF;AAClF,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,kBAAkB,GAC3C,MAAM,CAAC,sBAAsB,EAAE,mBAAmB,CAAC,CAuCrD"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { Component } from '@forgeax/engine-ecs';
|
|
2
|
+
import type { MountOverride } from '@forgeax/engine-types';
|
|
3
|
+
/**
|
|
4
|
+
* A single handle-field reference extracted from a SceneAsset entity.
|
|
5
|
+
*
|
|
6
|
+
* `entityLocalId` is the `node.localId`; `componentName` and `fieldName`
|
|
7
|
+
* identify the schema field whose `fieldType` starts with `shared\<` or
|
|
8
|
+
* `array\<shared\<`. `guidString` is the raw GUID string value from the
|
|
9
|
+
* entity's component data (NOT a parsed `AssetGuid` — callers parse or
|
|
10
|
+
* resolve as needed).
|
|
11
|
+
*
|
|
12
|
+
* `arrayIndex` is `undefined` for plain `handle<T>` fields; for
|
|
13
|
+
* `array<handle<T>>` fields it is the 0-based index into the array.
|
|
14
|
+
*/
|
|
15
|
+
export interface SceneHandleFieldEntry {
|
|
16
|
+
readonly entityLocalId: number;
|
|
17
|
+
readonly componentName: string;
|
|
18
|
+
readonly fieldName: string;
|
|
19
|
+
readonly guidString: string;
|
|
20
|
+
/** 0-based index for `array<handle<T>>` elements; `undefined` for plain `handle<T>` fields. */
|
|
21
|
+
readonly arrayIndex?: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Shape of a single entity passed to {@link extractSceneEntityHandleGuids}.
|
|
25
|
+
*
|
|
26
|
+
* Compatible with both `SceneEntity` (from `@forgeax/engine-types`, where
|
|
27
|
+
* `components` is `Partial<ComponentValuesMap>`) and test-side plain objects.
|
|
28
|
+
*/
|
|
29
|
+
interface SceneEntityLike {
|
|
30
|
+
readonly localId: number;
|
|
31
|
+
readonly components: Record<string, Record<string, unknown>>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Walk every `SceneEntityLike` in `entities` and extract all GUID strings
|
|
35
|
+
* bound to schema fields with `handle<...>` or `array<handle<...>>` fieldType.
|
|
36
|
+
*
|
|
37
|
+
* Unknown component names (absent from the supplied World-local catalog) are
|
|
38
|
+
* silently skipped — the ecs layer's `additionalProperties` check will catch
|
|
39
|
+
* unknowns at spawn time if appropriate.
|
|
40
|
+
*
|
|
41
|
+
* Values that are already numbers (resolved Handles) or non-strings are
|
|
42
|
+
* skipped (they are not GUID refs).
|
|
43
|
+
*
|
|
44
|
+
* @internal Shared by {@link AssetRegistry._resolveSceneGuids} and
|
|
45
|
+
* `buildSceneChildContext` as the entity-walk fallback used when the structured
|
|
46
|
+
* `envelope.refs` edges are unavailable or carry no per-entity detail.
|
|
47
|
+
*/
|
|
48
|
+
export declare function extractSceneEntityHandleGuids(components: ReadonlyMap<string, Component>, entities: ReadonlyArray<SceneEntityLike>): SceneHandleFieldEntry[];
|
|
49
|
+
/**
|
|
50
|
+
* One handle-field GUID reference extracted from a {@link MountOverride}'s value
|
|
51
|
+
* (feat-20260713 M3 / w12). Mirrors {@link SceneHandleFieldEntry} but keys on the
|
|
52
|
+
* override's array index (there is no entity `localId` — an override targets a
|
|
53
|
+
* mount member by its own `localId`, resolved by the ecs apply loop, not here).
|
|
54
|
+
*
|
|
55
|
+
* `fieldName` is the schema field the GUID binds to: the override's own `field`
|
|
56
|
+
* for the patch form, or a key of the component-add value map for the add form.
|
|
57
|
+
*/
|
|
58
|
+
export interface MountOverrideHandleFieldEntry {
|
|
59
|
+
/** 0-based index into the `overrides[]` array passed to the extractor. */
|
|
60
|
+
readonly overrideIndex: number;
|
|
61
|
+
readonly componentName: string;
|
|
62
|
+
readonly fieldName: string;
|
|
63
|
+
readonly guidString: string;
|
|
64
|
+
/** 0-based index for `array<shared<T>>` elements; `undefined` for scalar `shared<T>`. */
|
|
65
|
+
readonly arrayIndex?: number;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Walk `overrides` and extract every GUID string bound to a `shared<...>` /
|
|
69
|
+
* `array<shared<...>>` schema field inside each override's value (feat-20260713
|
|
70
|
+
* M3 / w12, plan-strategy D-2). This is the apply-side counterpart to
|
|
71
|
+
* {@link extractSceneEntityHandleGuids}: it feeds `resolveMountsRec`'s
|
|
72
|
+
* GUID→handle down-drill so a `mounts[].overrides[].value` carrying a raw GUID
|
|
73
|
+
* (e.g. an `AnimationPlayer.clips` clip GUID) resolves to a live handle before
|
|
74
|
+
* the ecs apply loop, which only ever sees numeric handles (D-2: the GUID domain
|
|
75
|
+
* stays sealed in assets-runtime).
|
|
76
|
+
*
|
|
77
|
+
* The `{comp, field?, value}` discriminant is normalized to `(fieldName, value)`
|
|
78
|
+
* pairs: the patch form (`field` present) yields one pair; the component-add form
|
|
79
|
+
* (`field` absent, `value` is a per-field map) yields one pair per value key.
|
|
80
|
+
* Field type is judged from the supplied catalog token schema, the same
|
|
81
|
+
* schema SSOT the entity walk uses. Unknown components / non-shared fields /
|
|
82
|
+
* non-string (already-resolved number) values are skipped (D-8 number pass-through).
|
|
83
|
+
*
|
|
84
|
+
* @internal Shared identification core; resolution lives in `resolveMountsRec`.
|
|
85
|
+
*/
|
|
86
|
+
export declare function extractMountOverrideHandleGuids(components: ReadonlyMap<string, Component>, overrides: ReadonlyArray<MountOverride>): MountOverrideHandleFieldEntry[];
|
|
87
|
+
export {};
|
|
88
|
+
//# sourceMappingURL=scene-handle-fields.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scene-handle-fields.d.ts","sourceRoot":"","sources":["../src/scene-handle-fields.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,+FAA+F;IAC/F,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;GAKG;AACH,UAAU,eAAe;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC9D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,EAC1C,QAAQ,EAAE,aAAa,CAAC,eAAe,CAAC,GACvC,qBAAqB,EAAE,CAmCzB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,6BAA6B;IAC5C,0EAA0E;IAC1E,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,yFAAyF;IACzF,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,+BAA+B,CAC7C,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,EAC1C,SAAS,EAAE,aAAa,CAAC,aAAa,CAAC,GACtC,6BAA6B,EAAE,CAwBjC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { SceneAsset } from '@forgeax/engine-types';
|
|
2
|
+
/**
|
|
3
|
+
* Structured error returned by parseScenePayload when a refs index is
|
|
4
|
+
* out of bounds (F-2 / AC-02).
|
|
5
|
+
*/
|
|
6
|
+
interface ParseSceneError {
|
|
7
|
+
readonly localId: number;
|
|
8
|
+
readonly component: string;
|
|
9
|
+
readonly field: string;
|
|
10
|
+
readonly index: number;
|
|
11
|
+
readonly refsLength: number;
|
|
12
|
+
}
|
|
13
|
+
export declare function parseScenePayload(payload: Record<string, unknown>, refs?: string[]): SceneAsset | ParseSceneError | undefined;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=scene-payload.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scene-payload.d.ts","sourceRoot":"","sources":["../src/scene-payload.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAEV,UAAU,EAGX,MAAM,uBAAuB,CAAC;AAG/B;;;GAGG;AACH,UAAU,eAAe;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAsBD,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,IAAI,CAAC,EAAE,MAAM,EAAE,GACd,UAAU,GAAG,eAAe,GAAG,SAAS,CAoG1C"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Loader } from '@forgeax/engine-types';
|
|
2
|
+
import { LoaderRegistry } from './loader-registry';
|
|
3
|
+
/**
|
|
4
|
+
* Wire the engine's default loader set (16 ordinary kinds plus UI) plus any
|
|
5
|
+
* `extraLoaders` onto `registry` in
|
|
6
|
+
* one call. Returns the same `registry` for chaining (so `wireDefaultLoaders(new
|
|
7
|
+
* LoaderRegistry())` is a one-expression wired registry). The `extraLoaders` are
|
|
8
|
+
* appended after the defaults and must use kinds outside the ordinary set.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { LoaderRegistry, wireDefaultLoaders } from '@forgeax/engine-assets-runtime';
|
|
13
|
+
* const loaders = wireDefaultLoaders(new LoaderRegistry());
|
|
14
|
+
* // loaders.get('mesh') / .get('texture') / .get('font') / .get('video') are
|
|
15
|
+
* // non-undefined; all ordinary Asset kinds share this same owner table.
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare function wireDefaultLoaders(registry: LoaderRegistry, extraLoaders?: readonly Loader[]): LoaderRegistry;
|
|
19
|
+
/**
|
|
20
|
+
* Convenience factory: a fresh `LoaderRegistry` pre-wired with the default
|
|
21
|
+
* loader set (plus any `extraLoaders`). The production assembly point
|
|
22
|
+
* (`createRenderer`) and tests pass the result into `new LoaderRegistry()` (D-7
|
|
23
|
+
* constructor-injection; loaders always wired at construction -- used by
|
|
24
|
+
* `AssetRegistry` internally via `createDefaultLoaderRegistry(extraLoaders)` and
|
|
25
|
+
* by host code / tests independently) -- no setter / no illegal intermediate
|
|
26
|
+
* state).
|
|
27
|
+
*/
|
|
28
|
+
export declare function createDefaultLoaderRegistry(extraLoaders?: readonly Loader[]): LoaderRegistry;
|
|
29
|
+
//# sourceMappingURL=wire-default-loaders.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wire-default-loaders.d.ts","sourceRoot":"","sources":["../src/wire-default-loaders.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAEpD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAanD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,cAAc,EACxB,YAAY,GAAE,SAAS,MAAM,EAAO,GACnC,cAAc,CAahB;AAED;;;;;;;;GAQG;AACH,wBAAgB,2BAA2B,CAAC,YAAY,GAAE,SAAS,MAAM,EAAO,GAAG,cAAc,CAEhG"}
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forgeax/engine-assets-runtime",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"sideEffects": false,
|
|
8
|
-
"description": "
|
|
8
|
+
"description": "Asset registry, loader registry, GUID resolution, and default loader wiring for forgeax-engine (Tier 2.1 -- extracted from @forgeax/engine-runtime).",
|
|
9
9
|
"exports": {
|
|
10
10
|
".": {
|
|
11
11
|
"types": "./dist/index.d.ts",
|
|
@@ -26,7 +26,23 @@
|
|
|
26
26
|
"LICENSE"
|
|
27
27
|
],
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@forgeax/engine-
|
|
29
|
+
"@forgeax/engine-codec": "0.1.6",
|
|
30
|
+
"@forgeax/engine-ecs": "0.1.6",
|
|
31
|
+
"@forgeax/engine-geometry": "0.1.6",
|
|
32
|
+
"@forgeax/engine-graphics-extras": "0.1.6",
|
|
33
|
+
"@forgeax/engine-image": "0.1.6",
|
|
34
|
+
"@forgeax/engine-pack": "0.1.6",
|
|
35
|
+
"@forgeax/engine-plugin": "0.1.6",
|
|
36
|
+
"@forgeax/engine-rhi": "0.1.6",
|
|
37
|
+
"@forgeax/engine-scene": "0.1.6",
|
|
38
|
+
"@forgeax/engine-shader": "0.1.6",
|
|
39
|
+
"@forgeax/engine-types": "0.1.6",
|
|
40
|
+
"@forgeax/engine-ui": "0.1.6",
|
|
41
|
+
"@webgpu/types": "^0.1.71"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@forgeax/engine-skinning": "0.1.6",
|
|
45
|
+
"@webgpu/types": "^0.1.71"
|
|
30
46
|
},
|
|
31
47
|
"forgeax": {
|
|
32
48
|
"metrics": {
|
|
@@ -40,9 +56,8 @@
|
|
|
40
56
|
"reason": "asset registry / loader library, no runtime canvas; fps reported by hello-* apps that consume it"
|
|
41
57
|
},
|
|
42
58
|
"bench": {
|
|
43
|
-
"enabled":
|
|
44
|
-
"
|
|
45
|
-
"reportPath": "report/assets-runtime-core.json"
|
|
59
|
+
"enabled": false,
|
|
60
|
+
"reason": "asset catalogue + load pipeline run at asset-load time, not per-frame; no CI micro-benchmark warranted"
|
|
46
61
|
},
|
|
47
62
|
"gate": {
|
|
48
63
|
"enabled": false,
|
|
@@ -56,8 +71,6 @@
|
|
|
56
71
|
},
|
|
57
72
|
"scripts": {
|
|
58
73
|
"build": "tsup",
|
|
59
|
-
"test": "vitest run"
|
|
60
|
-
"bench:asset-runtime-baseline": "node ../../scripts/metrics/asset-runtime-baseline.mjs",
|
|
61
|
-
"bench:asset-runtime-core": "node ../../scripts/metrics/asset-runtime-bench.mjs"
|
|
74
|
+
"test": "vitest run"
|
|
62
75
|
}
|
|
63
76
|
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// @forgeax/engine-assets-runtime -- withMeshAabb / computeAABB coverage
|
|
2
|
+
// (fix issue #709: assets-runtime src entered the coverage pool via the
|
|
3
|
+
// package's own tests importing `../` relative paths -> src; before this the
|
|
4
|
+
// module was only exercised through the compiled dist by runtime-project
|
|
5
|
+
// tests, which are excluded from the coverage denominator).
|
|
6
|
+
|
|
7
|
+
import type { MeshAsset } from '@forgeax/engine-types';
|
|
8
|
+
import { describe, expect, it } from 'vitest';
|
|
9
|
+
import { withMeshAabb } from '../aabb';
|
|
10
|
+
|
|
11
|
+
const EMPTY_BOX = [Infinity, Infinity, Infinity, -Infinity, -Infinity, -Infinity];
|
|
12
|
+
|
|
13
|
+
function meshWith(position: Float32Array | ArrayBuffer | undefined): MeshAsset {
|
|
14
|
+
return {
|
|
15
|
+
kind: 'mesh',
|
|
16
|
+
vertices: new Float32Array(0),
|
|
17
|
+
attributes: position === undefined ? {} : { position },
|
|
18
|
+
submeshes: [
|
|
19
|
+
{ indexOffset: 0, indexCount: 0, vertexCount: 0, topology: 'triangle-list', materialSlot: 0 },
|
|
20
|
+
],
|
|
21
|
+
materialSlots: [{ slotName: 'Default' }],
|
|
22
|
+
} as MeshAsset;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
describe('withMeshAabb', () => {
|
|
26
|
+
it('computes [min, max] over every (x, y, z) triple of the position attribute', () => {
|
|
27
|
+
const position = Float32Array.of(
|
|
28
|
+
-1,
|
|
29
|
+
-2,
|
|
30
|
+
-3, //
|
|
31
|
+
4,
|
|
32
|
+
5,
|
|
33
|
+
6, //
|
|
34
|
+
0,
|
|
35
|
+
0,
|
|
36
|
+
0,
|
|
37
|
+
);
|
|
38
|
+
const out = withMeshAabb(meshWith(position));
|
|
39
|
+
expect(Array.from(out.aabb as Float32Array)).toEqual([-1, -2, -3, 4, 5, 6]);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('handles a single-vertex mesh (min === max === that vertex)', () => {
|
|
43
|
+
const out = withMeshAabb(meshWith(Float32Array.of(7, 8, 9)));
|
|
44
|
+
expect(Array.from(out.aabb as Float32Array)).toEqual([7, 8, 9, 7, 8, 9]);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('re-wraps an ArrayBuffer position buffer as Float32Array', () => {
|
|
48
|
+
const buf = Float32Array.of(1, 1, 1, 2, 3, 4).buffer;
|
|
49
|
+
const out = withMeshAabb(meshWith(buf));
|
|
50
|
+
expect(Array.from(out.aabb as Float32Array)).toEqual([1, 1, 1, 2, 3, 4]);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('returns the inverted-infinity empty box when position is absent', () => {
|
|
54
|
+
const out = withMeshAabb(meshWith(undefined));
|
|
55
|
+
expect(Array.from(out.aabb as Float32Array)).toEqual(EMPTY_BOX);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('returns the empty box when position has fewer than 3 floats', () => {
|
|
59
|
+
const out = withMeshAabb(meshWith(Float32Array.of(1, 2)));
|
|
60
|
+
expect(Array.from(out.aabb as Float32Array)).toEqual(EMPTY_BOX);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('returns the empty box for a Uint16Array position (treated as absent)', () => {
|
|
64
|
+
const mesh = {
|
|
65
|
+
kind: 'mesh',
|
|
66
|
+
vertices: new Float32Array(0),
|
|
67
|
+
attributes: { position: Uint16Array.of(1, 2, 3) },
|
|
68
|
+
submeshes: [{ indexOffset: 0, indexCount: 0, vertexCount: 0, topology: 'triangle-list' }],
|
|
69
|
+
} as unknown as MeshAsset;
|
|
70
|
+
const out = withMeshAabb(mesh);
|
|
71
|
+
expect(Array.from(out.aabb as Float32Array)).toEqual(EMPTY_BOX);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('preserves a packed AABB when the binary path omits position attributes', () => {
|
|
75
|
+
const mesh = {
|
|
76
|
+
...meshWith(undefined),
|
|
77
|
+
aabb: Float32Array.of(-2, 0, -1, 3, 4, 5),
|
|
78
|
+
};
|
|
79
|
+
const out = withMeshAabb(mesh);
|
|
80
|
+
expect(Array.from(out.aabb as Float32Array)).toEqual([-2, 0, -1, 3, 4, 5]);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('mutates the mesh in place when it is extensible (returns same reference)', () => {
|
|
84
|
+
const mesh = meshWith(Float32Array.of(0, 0, 0, 1, 1, 1));
|
|
85
|
+
const out = withMeshAabb(mesh);
|
|
86
|
+
expect(out).toBe(mesh);
|
|
87
|
+
expect(mesh.aabb).toBeInstanceOf(Float32Array);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('returns a shallow copy carrying the aabb when the mesh is frozen', () => {
|
|
91
|
+
const mesh = Object.freeze(meshWith(Float32Array.of(0, 0, 0, 2, 2, 2)));
|
|
92
|
+
const out = withMeshAabb(mesh);
|
|
93
|
+
expect(out).not.toBe(mesh);
|
|
94
|
+
expect(Array.from(out.aabb as Float32Array)).toEqual([0, 0, 0, 2, 2, 2]);
|
|
95
|
+
expect(mesh.aabb).toBeUndefined();
|
|
96
|
+
});
|
|
97
|
+
});
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import type { ArtifactDescriptor } from '@forgeax/engine-types';
|
|
2
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
3
|
+
import { readArtifact } from '../registry/artifact-io';
|
|
4
|
+
|
|
5
|
+
const GUID = '22222222-2222-4222-8222-222222222222';
|
|
6
|
+
|
|
7
|
+
describe('artifact integrity and outer encoding', () => {
|
|
8
|
+
it('rejects an artifact without a durable media type', async () => {
|
|
9
|
+
const fetcher = vi.fn().mockResolvedValue(new Response(Uint8Array.of(1)));
|
|
10
|
+
const result = await readArtifact(
|
|
11
|
+
{
|
|
12
|
+
packageUrl: 'https://example.test/pkg.pack.json',
|
|
13
|
+
guid: GUID,
|
|
14
|
+
artifactKey: 'payload',
|
|
15
|
+
descriptor: {
|
|
16
|
+
path: 'payload.bin',
|
|
17
|
+
mediaType: '',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
fetcher,
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
expect(result.ok).toBe(false);
|
|
24
|
+
expect(fetcher).not.toHaveBeenCalled();
|
|
25
|
+
if (!result.ok) expect(result.error.code).toBe('asset-artifact-media-unsupported');
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('checks byte length and integrity after outer decoding', async () => {
|
|
29
|
+
const descriptor: ArtifactDescriptor = {
|
|
30
|
+
path: 'payload.bin',
|
|
31
|
+
mediaType: 'application/octet-stream',
|
|
32
|
+
contentEncoding: 'identity',
|
|
33
|
+
byteLength: 3,
|
|
34
|
+
integrity: {
|
|
35
|
+
algorithm: 'sha256',
|
|
36
|
+
digest: 'sha256-of-decoded-bytes',
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
const result = await readArtifact(
|
|
40
|
+
{
|
|
41
|
+
packageUrl: 'https://example.test/pkg.pack.json',
|
|
42
|
+
guid: GUID,
|
|
43
|
+
artifactKey: 'payload',
|
|
44
|
+
descriptor,
|
|
45
|
+
},
|
|
46
|
+
vi.fn().mockResolvedValue(new Response(Uint8Array.of(1, 2, 3))),
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
expect(result.ok).toBe(false);
|
|
50
|
+
if (!result.ok) {
|
|
51
|
+
expect(result.error.code).toBe('asset-artifact-integrity-mismatch');
|
|
52
|
+
expect(result.error.expected).toContain('sha256');
|
|
53
|
+
expect(result.error.detail.observed).toBeTruthy();
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('reports a same-sized published artifact with the wrong digest as an integrity mismatch', async () => {
|
|
58
|
+
const result = await readArtifact(
|
|
59
|
+
{
|
|
60
|
+
packageUrl: 'https://example.test/pkg.pack.json',
|
|
61
|
+
guid: GUID,
|
|
62
|
+
artifactKey: 'shader',
|
|
63
|
+
descriptor: {
|
|
64
|
+
path: 'shader.wgsl',
|
|
65
|
+
mediaType: 'text/wgsl',
|
|
66
|
+
byteLength: 4,
|
|
67
|
+
integrity: { algorithm: 'sha256', digest: 'sha256:published-digest' },
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
vi.fn().mockResolvedValue(new Response(Uint8Array.of(1, 2, 3, 4))),
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
expect(result).toMatchObject({
|
|
74
|
+
ok: false,
|
|
75
|
+
error: { code: 'asset-artifact-integrity-mismatch' },
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('does not pass asset codec names to the outer decoder', async () => {
|
|
80
|
+
const fetcher = vi.fn().mockResolvedValue(new Response(Uint8Array.of(7, 8)));
|
|
81
|
+
const result = await readArtifact(
|
|
82
|
+
{
|
|
83
|
+
packageUrl: 'https://example.test/pkg.pack.json',
|
|
84
|
+
guid: GUID,
|
|
85
|
+
artifactKey: 'texture',
|
|
86
|
+
descriptor: {
|
|
87
|
+
path: 'texture.data',
|
|
88
|
+
mediaType: 'image/ktx2',
|
|
89
|
+
assetCodec: { name: 'basis', profile: 'etc1s' },
|
|
90
|
+
contentEncoding: 'identity',
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
fetcher,
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
expect(result).toEqual({ ok: true, value: Uint8Array.of(7, 8) });
|
|
97
|
+
expect(fetcher).toHaveBeenCalledTimes(1);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import type { ArtifactDescriptor } from '@forgeax/engine-types';
|
|
2
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
3
|
+
import { readArtifact } from '../registry/artifact-io';
|
|
4
|
+
|
|
5
|
+
const GUID = '11111111-1111-4111-8111-111111111111';
|
|
6
|
+
|
|
7
|
+
function descriptor(path: string, changes: Partial<ArtifactDescriptor> = {}): ArtifactDescriptor {
|
|
8
|
+
return { path, mediaType: 'application/octet-stream', ...changes };
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function response(bytes: Uint8Array, ok = true): Response {
|
|
12
|
+
const body = new ArrayBuffer(bytes.byteLength);
|
|
13
|
+
new Uint8Array(body).set(bytes);
|
|
14
|
+
return new Response(body, { status: ok ? 200 : 404 });
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
describe('artifact I/O', () => {
|
|
18
|
+
it('rejects an empty media type before fetching artifact bytes', async () => {
|
|
19
|
+
const fetcher = vi.fn();
|
|
20
|
+
const result = await readArtifact(
|
|
21
|
+
{
|
|
22
|
+
packageUrl: 'https://example.test/packages/main.pack.json',
|
|
23
|
+
guid: GUID,
|
|
24
|
+
artifactKey: 'source',
|
|
25
|
+
descriptor: descriptor('payload.bin', { mediaType: '' }),
|
|
26
|
+
},
|
|
27
|
+
fetcher,
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
expect(result.ok).toBe(false);
|
|
31
|
+
expect(fetcher).not.toHaveBeenCalled();
|
|
32
|
+
if (!result.ok) expect(result.error.code).toBe('asset-artifact-media-unsupported');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it.each([
|
|
36
|
+
'../outside.bin',
|
|
37
|
+
'%2e%2e/outside.bin',
|
|
38
|
+
'%252e%252e/outside.bin',
|
|
39
|
+
'/absolute.bin',
|
|
40
|
+
'https://evil.example/outside.bin',
|
|
41
|
+
'..\\outside.bin',
|
|
42
|
+
])('rejects unsafe locator %s before reading', async (path) => {
|
|
43
|
+
const fetcher = vi.fn();
|
|
44
|
+
const result = await readArtifact(
|
|
45
|
+
{
|
|
46
|
+
packageUrl: 'https://example.test/packages/main.pack.json',
|
|
47
|
+
guid: GUID,
|
|
48
|
+
artifactKey: 'source',
|
|
49
|
+
descriptor: descriptor(path),
|
|
50
|
+
},
|
|
51
|
+
fetcher,
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
expect(result.ok).toBe(false);
|
|
55
|
+
expect(fetcher).not.toHaveBeenCalled();
|
|
56
|
+
if (!result.ok) {
|
|
57
|
+
expect(result.error.code).toBe('asset-artifact-path-invalid');
|
|
58
|
+
expect(result.error.detail.guid).toBe(GUID);
|
|
59
|
+
expect(result.error.detail.artifactKey).toBe('source');
|
|
60
|
+
expect(result.error.hint).toContain('package-relative');
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('reads a normalized package-relative artifact and preserves asset codec metadata as data', async () => {
|
|
65
|
+
const fetcher = vi.fn().mockResolvedValue(response(Uint8Array.of(1, 2, 3)));
|
|
66
|
+
const result = await readArtifact(
|
|
67
|
+
{
|
|
68
|
+
packageUrl: 'https://example.test/packages/main.pack.json',
|
|
69
|
+
guid: GUID,
|
|
70
|
+
artifactKey: 'source',
|
|
71
|
+
descriptor: descriptor('./payload.bin', {
|
|
72
|
+
mediaType: 'image/ktx2',
|
|
73
|
+
assetCodec: { name: 'basis', profile: 'uastc' },
|
|
74
|
+
contentEncoding: 'identity',
|
|
75
|
+
}),
|
|
76
|
+
},
|
|
77
|
+
fetcher,
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
expect(result).toEqual({ ok: true, value: Uint8Array.of(1, 2, 3) });
|
|
81
|
+
expect(fetcher).toHaveBeenCalledWith('https://example.test/packages/payload.bin');
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('returns structured missing, encoding, and integrity failures', async () => {
|
|
85
|
+
const missing = await readArtifact(
|
|
86
|
+
{
|
|
87
|
+
packageUrl: 'https://example.test/main.pack.json',
|
|
88
|
+
guid: GUID,
|
|
89
|
+
artifactKey: 'source',
|
|
90
|
+
descriptor: descriptor('missing.bin'),
|
|
91
|
+
},
|
|
92
|
+
vi.fn().mockResolvedValue(response(new Uint8Array(), false)),
|
|
93
|
+
);
|
|
94
|
+
expect(missing.ok).toBe(false);
|
|
95
|
+
if (!missing.ok) expect(missing.error.code).toBe('asset-artifact-missing');
|
|
96
|
+
|
|
97
|
+
const unsupported = await readArtifact(
|
|
98
|
+
{
|
|
99
|
+
packageUrl: 'https://example.test/main.pack.json',
|
|
100
|
+
guid: GUID,
|
|
101
|
+
artifactKey: 'source',
|
|
102
|
+
descriptor: descriptor('payload.bin', { contentEncoding: 'brotli' as never }),
|
|
103
|
+
},
|
|
104
|
+
vi.fn(),
|
|
105
|
+
);
|
|
106
|
+
expect(unsupported.ok).toBe(false);
|
|
107
|
+
if (!unsupported.ok) expect(unsupported.error.code).toBe('asset-artifact-encoding-unsupported');
|
|
108
|
+
|
|
109
|
+
const integrity = await readArtifact(
|
|
110
|
+
{
|
|
111
|
+
packageUrl: 'https://example.test/main.pack.json',
|
|
112
|
+
guid: GUID,
|
|
113
|
+
artifactKey: 'source',
|
|
114
|
+
descriptor: descriptor('payload.bin', {
|
|
115
|
+
integrity: { algorithm: 'sha256', digest: 'not-the-digest' },
|
|
116
|
+
}),
|
|
117
|
+
},
|
|
118
|
+
vi.fn().mockResolvedValue(response(Uint8Array.of(1, 2, 3))),
|
|
119
|
+
);
|
|
120
|
+
expect(integrity.ok).toBe(false);
|
|
121
|
+
if (!integrity.ok) {
|
|
122
|
+
expect(integrity.error.code).toBe('asset-artifact-integrity-mismatch');
|
|
123
|
+
expect(integrity.error.detail.guid).toBe(GUID);
|
|
124
|
+
expect(integrity.error.detail.artifactKey).toBe('source');
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { createRuntimeAssetEvidenceAdapter } from '../registry/asset-evidence.js';
|
|
3
|
+
|
|
4
|
+
const guid = '11111111-1111-4111-8111-111111111111';
|
|
5
|
+
|
|
6
|
+
describe('AssetEvidence SDK integration', () => {
|
|
7
|
+
it('uses the same projector shape for inspect and verifyByGuid', async () => {
|
|
8
|
+
const adapter = createRuntimeAssetEvidenceAdapter({
|
|
9
|
+
evidence: async () => ({
|
|
10
|
+
guid,
|
|
11
|
+
source: { origin: 'sourceMeta', inputFingerprint: 'fp-1' },
|
|
12
|
+
locator: { packageUrl: '/assets/config.pack.json' },
|
|
13
|
+
receipt: {
|
|
14
|
+
guid,
|
|
15
|
+
origin: 'sourceMeta',
|
|
16
|
+
status: 'succeeded',
|
|
17
|
+
inputFingerprint: 'fp-1',
|
|
18
|
+
outputDigest: 'digest-1',
|
|
19
|
+
},
|
|
20
|
+
packageVerification: { status: 'passed', digest: 'digest-1' },
|
|
21
|
+
artifacts: {},
|
|
22
|
+
runtime: { status: 'ready' },
|
|
23
|
+
}),
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const inspected = await adapter.inspect(guid);
|
|
27
|
+
const verified = await adapter.verifyByGuid(guid);
|
|
28
|
+
expect(inspected.ok).toBe(true);
|
|
29
|
+
expect(verified.ok).toBe(true);
|
|
30
|
+
expect(inspected).toEqual(verified);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { createRuntimeAssetEvidenceAdapter } from '../registry/asset-evidence.js';
|
|
3
|
+
|
|
4
|
+
const guid = '11111111-1111-4111-8111-111111111111';
|
|
5
|
+
|
|
6
|
+
describe('runtime AssetEvidence adapter', () => {
|
|
7
|
+
it('uses injected runtime state and leaves missing capability explicit', async () => {
|
|
8
|
+
const adapter = createRuntimeAssetEvidenceAdapter({
|
|
9
|
+
evidence: async (requestedGuid) => ({
|
|
10
|
+
guid: requestedGuid,
|
|
11
|
+
source: { origin: 'sourceMeta', inputFingerprint: 'fp-1' },
|
|
12
|
+
locator: { packageUrl: '/assets/data.pack.json' },
|
|
13
|
+
receipt: {
|
|
14
|
+
guid: requestedGuid,
|
|
15
|
+
origin: 'sourceMeta',
|
|
16
|
+
status: 'succeeded',
|
|
17
|
+
inputFingerprint: 'fp-1',
|
|
18
|
+
outputDigest: 'digest-1',
|
|
19
|
+
},
|
|
20
|
+
packageVerification: { status: 'passed', digest: 'digest-1' },
|
|
21
|
+
artifacts: {},
|
|
22
|
+
}),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const result = await adapter.verifyByGuid(guid);
|
|
26
|
+
expect(result.ok).toBe(true);
|
|
27
|
+
if (!result.ok) return;
|
|
28
|
+
expect(result.value.guid).toBe(guid);
|
|
29
|
+
expect(result.value.runtime.status).toBe('unknown');
|
|
30
|
+
expect(result.value.cook.freshness).toBe('current');
|
|
31
|
+
});
|
|
32
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AssetKindPayload } from '@forgeax/engine-types';
|
|
2
2
|
import { describe, expect, it } from 'vitest';
|
|
3
|
-
import { defineAssetKind } from '../
|
|
3
|
+
import { defineAssetKind } from '../index.js';
|
|
4
4
|
|
|
5
5
|
describe('defineAssetKind', () => {
|
|
6
6
|
it('freezes the runtime kind witness while preserving its payload type', () => {
|