@forgeax/engine-assets-runtime 0.1.4 → 0.1.7
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 +453 -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 +554 -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 +143 -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 +7233 -114
- package/dist/index.mjs.map +1 -1
- package/dist/internal.d.ts +1 -1
- package/dist/internal.d.ts.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 +508 -0
- package/src/__tests__/material-stale-generation.unit.test.ts +147 -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 +27 -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 +2045 -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 +186 -0
- package/src/image-error.ts +45 -0
- package/src/index.ts +183 -16
- package/src/internal.ts +1 -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 +385 -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,259 @@
|
|
|
1
|
+
import { decompressZstd } from '@forgeax/engine-codec';
|
|
2
|
+
import { validateArtifactPath } from '@forgeax/engine-pack';
|
|
3
|
+
import type { ArtifactDescriptor, AssetArtifactError } from '@forgeax/engine-types';
|
|
4
|
+
import { err, ok, type Result } from '@forgeax/engine-types';
|
|
5
|
+
|
|
6
|
+
export interface ArtifactReadRequest {
|
|
7
|
+
readonly packageUrl: string;
|
|
8
|
+
readonly guid: string;
|
|
9
|
+
readonly artifactKey: string;
|
|
10
|
+
readonly descriptor: ArtifactDescriptor;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type ArtifactFetcher = (url: string) => Promise<Response>;
|
|
14
|
+
|
|
15
|
+
function failure(
|
|
16
|
+
code: AssetArtifactError['code'],
|
|
17
|
+
request: ArtifactReadRequest,
|
|
18
|
+
expected: string,
|
|
19
|
+
hint: string,
|
|
20
|
+
observed: string,
|
|
21
|
+
): AssetArtifactError {
|
|
22
|
+
if (code === 'asset-artifact-missing') {
|
|
23
|
+
return {
|
|
24
|
+
code,
|
|
25
|
+
expected,
|
|
26
|
+
hint,
|
|
27
|
+
detail: {
|
|
28
|
+
guid: request.guid,
|
|
29
|
+
artifactKey: request.artifactKey,
|
|
30
|
+
path: request.descriptor.path,
|
|
31
|
+
observed,
|
|
32
|
+
expected,
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
code,
|
|
38
|
+
expected,
|
|
39
|
+
hint,
|
|
40
|
+
detail: {
|
|
41
|
+
guid: request.guid,
|
|
42
|
+
artifactKey: request.artifactKey,
|
|
43
|
+
observed,
|
|
44
|
+
expected,
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function artifactUrl(packageUrl: string, path: string): string {
|
|
50
|
+
try {
|
|
51
|
+
return new URL(path, packageUrl).toString();
|
|
52
|
+
} catch {
|
|
53
|
+
const queryIndex = packageUrl.search(/[?#]/);
|
|
54
|
+
const cleanPackageUrl = queryIndex < 0 ? packageUrl : packageUrl.slice(0, queryIndex);
|
|
55
|
+
const slash = cleanPackageUrl.lastIndexOf('/');
|
|
56
|
+
return `${slash < 0 ? '' : cleanPackageUrl.slice(0, slash + 1)}${path}`;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function encodedBytes(bytes: Uint8Array): string {
|
|
61
|
+
let binary = '';
|
|
62
|
+
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
63
|
+
return globalThis.btoa(binary);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function hexBytes(bytes: Uint8Array): string {
|
|
67
|
+
return [...bytes].map((byte) => byte.toString(16).padStart(2, '0')).join('');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function sha256(bytes: Uint8Array): Promise<{ base64: string; hex: string } | undefined> {
|
|
71
|
+
const subtle = globalThis.crypto?.subtle;
|
|
72
|
+
if (subtle === undefined) return undefined;
|
|
73
|
+
const digest = await subtle.digest('SHA-256', bytes.slice().buffer as ArrayBuffer);
|
|
74
|
+
const digestBytes = new Uint8Array(digest);
|
|
75
|
+
return { base64: encodedBytes(digestBytes), hex: hexBytes(digestBytes) };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function decodeOuter(
|
|
79
|
+
bytes: Uint8Array,
|
|
80
|
+
request: ArtifactReadRequest,
|
|
81
|
+
): Promise<Result<Uint8Array, AssetArtifactError>> {
|
|
82
|
+
const encoding = request.descriptor.contentEncoding ?? 'identity';
|
|
83
|
+
if (encoding === 'identity') return ok(bytes);
|
|
84
|
+
if (encoding !== 'zstd') {
|
|
85
|
+
return err(
|
|
86
|
+
failure(
|
|
87
|
+
'asset-artifact-encoding-unsupported',
|
|
88
|
+
request,
|
|
89
|
+
"contentEncoding 'identity' or 'zstd'",
|
|
90
|
+
'change the descriptor to a supported outer content encoding and re-cook the package',
|
|
91
|
+
encoding,
|
|
92
|
+
),
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
const decoded = await decompressZstd(bytes);
|
|
96
|
+
if (!decoded.ok) {
|
|
97
|
+
return err(
|
|
98
|
+
failure(
|
|
99
|
+
'asset-artifact-decode-failed',
|
|
100
|
+
request,
|
|
101
|
+
'valid bytes for the declared outer content encoding',
|
|
102
|
+
're-cook the artifact and verify the stored bytes before loading again',
|
|
103
|
+
JSON.stringify(decoded.error.detail),
|
|
104
|
+
),
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
return ok(decoded.value);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async function verifyBytes(
|
|
111
|
+
bytes: Uint8Array,
|
|
112
|
+
request: ArtifactReadRequest,
|
|
113
|
+
): Promise<Result<Uint8Array, AssetArtifactError>> {
|
|
114
|
+
const expectedLength = request.descriptor.byteLength;
|
|
115
|
+
if (expectedLength !== undefined && expectedLength !== bytes.byteLength) {
|
|
116
|
+
return err(
|
|
117
|
+
failure(
|
|
118
|
+
'asset-artifact-integrity-mismatch',
|
|
119
|
+
request,
|
|
120
|
+
`decoded artifact byteLength ${expectedLength}`,
|
|
121
|
+
're-cook the package or update its artifact descriptor to match the bytes',
|
|
122
|
+
String(bytes.byteLength),
|
|
123
|
+
),
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
const integrity = request.descriptor.integrity;
|
|
127
|
+
if (integrity === undefined) return ok(bytes);
|
|
128
|
+
const digest = await sha256(bytes);
|
|
129
|
+
if (digest === undefined) {
|
|
130
|
+
return err(
|
|
131
|
+
failure(
|
|
132
|
+
'asset-artifact-integrity-mismatch',
|
|
133
|
+
request,
|
|
134
|
+
'a runtime with Web Crypto SHA-256 support',
|
|
135
|
+
'enable Web Crypto or remove the unverifiable artifact from the package',
|
|
136
|
+
'crypto.subtle unavailable',
|
|
137
|
+
),
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
const expectedDigest = integrity.digest.startsWith('sha256:')
|
|
141
|
+
? integrity.digest.slice('sha256:'.length)
|
|
142
|
+
: integrity.digest;
|
|
143
|
+
if (expectedDigest !== digest.base64 && expectedDigest.toLowerCase() !== digest.hex) {
|
|
144
|
+
return err(
|
|
145
|
+
failure(
|
|
146
|
+
'asset-artifact-integrity-mismatch',
|
|
147
|
+
request,
|
|
148
|
+
`sha256 digest ${integrity.digest}`,
|
|
149
|
+
're-cook the artifact or replace the corrupted stored bytes',
|
|
150
|
+
digest.base64,
|
|
151
|
+
),
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
return ok(bytes);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export async function readArtifact(
|
|
158
|
+
request: ArtifactReadRequest,
|
|
159
|
+
fetcher: ArtifactFetcher = (url) => globalThis.fetch(url),
|
|
160
|
+
): Promise<Result<Uint8Array, AssetArtifactError>> {
|
|
161
|
+
if (request.descriptor.mediaType.trim().length === 0) {
|
|
162
|
+
return err(
|
|
163
|
+
failure(
|
|
164
|
+
'asset-artifact-media-unsupported',
|
|
165
|
+
request,
|
|
166
|
+
'a non-empty durable artifact mediaType',
|
|
167
|
+
'set the artifact mediaType during production and re-publish the package',
|
|
168
|
+
request.descriptor.mediaType,
|
|
169
|
+
),
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
const path = validateArtifactPath(request.descriptor.path, {
|
|
173
|
+
packageRoot: request.packageUrl,
|
|
174
|
+
guid: request.guid,
|
|
175
|
+
artifactKey: request.artifactKey,
|
|
176
|
+
});
|
|
177
|
+
if (!path.ok) return path;
|
|
178
|
+
|
|
179
|
+
const encoding = request.descriptor.contentEncoding ?? 'identity';
|
|
180
|
+
if (encoding !== 'identity' && encoding !== 'zstd') {
|
|
181
|
+
return err(
|
|
182
|
+
failure(
|
|
183
|
+
'asset-artifact-encoding-unsupported',
|
|
184
|
+
request,
|
|
185
|
+
"contentEncoding 'identity' or 'zstd'",
|
|
186
|
+
'change the descriptor to a supported outer content encoding and re-cook the package',
|
|
187
|
+
encoding,
|
|
188
|
+
),
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const url = artifactUrl(request.packageUrl, path.value);
|
|
193
|
+
let response: Response;
|
|
194
|
+
try {
|
|
195
|
+
response = await fetcher(url);
|
|
196
|
+
} catch (cause) {
|
|
197
|
+
return err(
|
|
198
|
+
failure(
|
|
199
|
+
'asset-artifact-missing',
|
|
200
|
+
request,
|
|
201
|
+
`readable artifact at ${path.value}`,
|
|
202
|
+
'publish the artifact at the declared package-relative path and retry the load',
|
|
203
|
+
cause instanceof Error ? cause.message : 'artifact fetch failed',
|
|
204
|
+
),
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
if (!response.ok) {
|
|
208
|
+
return err(
|
|
209
|
+
failure(
|
|
210
|
+
'asset-artifact-missing',
|
|
211
|
+
request,
|
|
212
|
+
`HTTP 200 for artifact at ${path.value}`,
|
|
213
|
+
'publish the missing artifact and retry the load',
|
|
214
|
+
`HTTP ${response.status}`,
|
|
215
|
+
),
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
let bytes: Uint8Array;
|
|
220
|
+
try {
|
|
221
|
+
bytes = new Uint8Array(await response.arrayBuffer());
|
|
222
|
+
} catch (cause) {
|
|
223
|
+
return err(
|
|
224
|
+
failure(
|
|
225
|
+
'asset-artifact-missing',
|
|
226
|
+
request,
|
|
227
|
+
`readable artifact at ${path.value}`,
|
|
228
|
+
'repair the published artifact and retry the load',
|
|
229
|
+
cause instanceof Error ? cause.message : 'artifact body unreadable',
|
|
230
|
+
),
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
const decoded = await decodeOuter(bytes, request);
|
|
234
|
+
if (!decoded.ok) return decoded;
|
|
235
|
+
return verifyBytes(decoded.value, request);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export class ArtifactReadCache {
|
|
239
|
+
private readonly cache = new Map<string, Promise<Result<Uint8Array, AssetArtifactError>>>();
|
|
240
|
+
|
|
241
|
+
read(
|
|
242
|
+
key: string,
|
|
243
|
+
reader: () => Promise<Result<Uint8Array, AssetArtifactError>>,
|
|
244
|
+
): Promise<Result<Uint8Array, AssetArtifactError>> {
|
|
245
|
+
const existing = this.cache.get(key);
|
|
246
|
+
if (existing !== undefined) return existing;
|
|
247
|
+
const pending = reader();
|
|
248
|
+
this.cache.set(key, pending);
|
|
249
|
+
void pending.then((result) => {
|
|
250
|
+
if (!result.ok) this.cache.delete(key);
|
|
251
|
+
});
|
|
252
|
+
return pending;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
clear(key?: string): void {
|
|
256
|
+
if (key === undefined) this.cache.clear();
|
|
257
|
+
else this.cache.delete(key);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type AssetEvidence,
|
|
3
|
+
type AssetEvidenceError,
|
|
4
|
+
type AssetEvidenceInputs,
|
|
5
|
+
err,
|
|
6
|
+
projectAssetEvidence,
|
|
7
|
+
type Result,
|
|
8
|
+
} from '@forgeax/engine-types';
|
|
9
|
+
|
|
10
|
+
/** Host-injected runtime bridge; the adapter never imports CLI, Vite, or Node policy. */
|
|
11
|
+
export interface RuntimeEvidenceSource {
|
|
12
|
+
readonly evidence: (
|
|
13
|
+
guid: string,
|
|
14
|
+
) => Promise<AssetEvidenceInputs | Result<AssetEvidenceInputs, AssetEvidenceError>>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Runtime SDK view over the shared AssetEvidence projector. */
|
|
18
|
+
export interface RuntimeAssetEvidenceAdapter {
|
|
19
|
+
readonly inspect: (guid: string) => Promise<Result<AssetEvidence, AssetEvidenceError>>;
|
|
20
|
+
readonly verifyByGuid: (guid: string) => Promise<Result<AssetEvidence, AssetEvidenceError>>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function missingCapability(guid: string): Result<never, AssetEvidenceError> {
|
|
24
|
+
return err({
|
|
25
|
+
code: 'asset-evidence-capability-missing',
|
|
26
|
+
expected: 'an injected runtime evidence source',
|
|
27
|
+
hint: 'configure an evidence source before calling inspect(guid) or verifyByGuid(guid)',
|
|
28
|
+
detail: { capability: 'runtime evidence source', stage: `guid:${guid}` },
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async function project(
|
|
33
|
+
source: RuntimeEvidenceSource,
|
|
34
|
+
guid: string,
|
|
35
|
+
): Promise<Result<AssetEvidence, AssetEvidenceError>> {
|
|
36
|
+
const input = await source.evidence(guid);
|
|
37
|
+
if ('ok' in input) {
|
|
38
|
+
if (!input.ok) return input;
|
|
39
|
+
return projectAssetEvidence(input.value);
|
|
40
|
+
}
|
|
41
|
+
return projectAssetEvidence(input);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Create an adapter; omitted source intentionally returns capability-missing errors. */
|
|
45
|
+
export function createRuntimeAssetEvidenceAdapter(
|
|
46
|
+
source?: RuntimeEvidenceSource,
|
|
47
|
+
): RuntimeAssetEvidenceAdapter {
|
|
48
|
+
const read = async (guid: string): Promise<Result<AssetEvidence, AssetEvidenceError>> =>
|
|
49
|
+
source === undefined ? missingCapability(guid) : project(source, guid);
|
|
50
|
+
return { inspect: read, verifyByGuid: read };
|
|
51
|
+
}
|