@forgeax/engine-pack 0.1.20 → 0.1.23
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 +159 -46
- package/dist/__tests__/inventory-schema.test.d.ts +2 -0
- package/dist/__tests__/inventory-schema.test.d.ts.map +1 -0
- package/dist/__tests__/parameterized-pack-authoring-gateway.unit.test.d.ts +2 -0
- package/dist/__tests__/parameterized-pack-authoring-gateway.unit.test.d.ts.map +1 -0
- package/dist/__tests__/parameterized-pack-scanner.unit.test.d.ts +2 -0
- package/dist/__tests__/parameterized-pack-scanner.unit.test.d.ts.map +1 -0
- package/dist/__tests__/parameterized-pack.unit.test.d.ts +2 -0
- package/dist/__tests__/parameterized-pack.unit.test.d.ts.map +1 -0
- package/dist/__tests__/scanner-blacklist.test.d.ts +2 -0
- package/dist/__tests__/scanner-blacklist.test.d.ts.map +1 -0
- package/dist/build.d.ts +9 -4
- package/dist/build.d.ts.map +1 -1
- package/dist/build.mjs +3317 -804
- package/dist/build.mjs.map +1 -1
- package/dist/builtin.mjs +37 -4
- package/dist/builtin.mjs.map +1 -1
- package/dist/catalog-builder.d.ts.map +1 -1
- package/dist/cli-asset.d.ts.map +1 -1
- package/dist/cli-asset.mjs +1368 -850
- package/dist/cli-asset.mjs.map +1 -1
- package/dist/deriveAssetName.d.ts +11 -7
- package/dist/deriveAssetName.d.ts.map +1 -1
- package/dist/evidence/material-cook.d.ts.map +1 -1
- package/dist/evidence/source-inventory.d.ts.map +1 -1
- package/dist/guid.d.ts +15 -0
- package/dist/guid.d.ts.map +1 -1
- package/dist/guid.mjs +53 -5
- package/dist/guid.mjs.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +1255 -561
- package/dist/index.mjs.map +1 -1
- package/dist/inventory/binding.d.ts +6 -0
- package/dist/inventory/binding.d.ts.map +1 -0
- package/dist/inventory/declaration.d.ts +24 -0
- package/dist/inventory/declaration.d.ts.map +1 -0
- package/dist/inventory/index.d.ts +3 -0
- package/dist/inventory/index.d.ts.map +1 -0
- package/dist/inventory/sync.d.ts +5 -0
- package/dist/inventory/sync.d.ts.map +1 -0
- package/dist/material-cook.mjs +3 -1
- package/dist/material-cook.mjs.map +1 -1
- package/dist/name.mjs +4 -7
- package/dist/name.mjs.map +1 -1
- package/dist/package-finalizer.d.ts +2 -20
- package/dist/package-finalizer.d.ts.map +1 -1
- package/dist/parameterized-pack-node.d.ts +26 -0
- package/dist/parameterized-pack-node.d.ts.map +1 -0
- package/dist/parameterized-pack-node.mjs +11093 -0
- package/dist/parameterized-pack-node.mjs.map +1 -0
- package/dist/parameterized-pack.d.ts +233 -0
- package/dist/parameterized-pack.d.ts.map +1 -0
- package/dist/resolve-asset-source.d.ts +1 -3
- package/dist/resolve-asset-source.d.ts.map +1 -1
- package/dist/resolve-asset-source.mjs +6 -81
- package/dist/resolve-asset-source.mjs.map +1 -1
- package/dist/runtime.mjs +77 -7
- package/dist/runtime.mjs.map +1 -1
- package/dist/scanner.d.ts +19 -8
- package/dist/scanner.d.ts.map +1 -1
- package/dist/scanner.mjs +1169 -690
- package/dist/scanner.mjs.map +1 -1
- package/dist/schema-compiled.d.ts.map +1 -1
- package/dist/schema.mjs +79 -7
- package/dist/schema.mjs.map +1 -1
- package/dist/scriptable-pack-node.d.ts +8 -32
- package/dist/scriptable-pack-node.d.ts.map +1 -1
- package/dist/scriptable-pack-node.mjs +576 -1021
- package/dist/scriptable-pack-node.mjs.map +1 -1
- package/dist/scriptable-pack-worker.mjs +29 -11
- package/dist/scriptable-pack-worker.mjs.map +1 -1
- package/dist/scriptable-pack.d.ts +19 -532
- package/dist/scriptable-pack.d.ts.map +1 -1
- package/dist/scriptable-pack.mjs +1042 -527
- package/dist/scriptable-pack.mjs.map +1 -1
- package/package.json +7 -7
- package/schema/meta.schema.json +1 -1
- package/schema/pack.schema.json +76 -6
- package/src/__tests__/guid-collision.unit.test.ts +18 -9
- package/src/__tests__/inventory-schema.test.ts +109 -0
- package/src/__tests__/pack.unit.test.ts +1 -238
- package/src/__tests__/package-finalizer.contract.test.ts +55 -0
- package/src/__tests__/parameterized-pack-authoring-gateway.unit.test.ts +249 -0
- package/src/__tests__/parameterized-pack-scanner.unit.test.ts +123 -0
- package/src/__tests__/parameterized-pack.unit.test.ts +266 -0
- package/src/__tests__/resolve-asset-source.test.ts +15 -98
- package/src/__tests__/scanner-blacklist.test.ts +55 -0
- package/src/__tests__/scanner-inventory.contract.test.ts +14 -15
- package/src/__tests__/scanner-inventory.test.ts +24 -12
- package/src/__tests__/scriptable-pack-cli.integration.test.ts +4 -9
- package/src/__tests__/topology.unit.test.ts +23 -0
- package/src/build.ts +28 -18
- package/src/catalog-builder.ts +61 -34
- package/src/cli-asset.ts +70 -85
- package/src/deriveAssetName.ts +14 -13
- package/src/evidence/material-cook.ts +3 -1
- package/src/evidence/source-inventory.ts +34 -21
- package/src/guid.ts +65 -4
- package/src/index.ts +12 -11
- package/src/inventory/binding.ts +25 -0
- package/src/inventory/declaration.ts +168 -0
- package/src/inventory/index.ts +18 -0
- package/src/inventory/sync.ts +22 -0
- package/src/package-finalizer.ts +2 -42
- package/src/parameterized-pack-node.ts +1968 -0
- package/src/parameterized-pack.ts +1493 -0
- package/src/resolve-asset-source.ts +4 -76
- package/src/scanner.ts +241 -59
- package/src/schema-compiled.ts +2 -0
- package/src/scriptable-pack-node.ts +111 -722
- package/src/scriptable-pack-worker.ts +48 -16
- package/src/scriptable-pack.ts +27 -939
- package/dist/.tsbuildinfo +0 -1
- package/dist/__tests__/load-asset-config.test.d.ts +0 -2
- package/dist/__tests__/load-asset-config.test.d.ts.map +0 -1
- package/dist/__tests__/scriptable-pack.test-d.d.ts +0 -2
- package/dist/__tests__/scriptable-pack.test-d.d.ts.map +0 -1
- package/dist/__tests__/scriptable-pack.unit.test.d.ts +0 -2
- package/dist/__tests__/scriptable-pack.unit.test.d.ts.map +0 -1
- package/dist/config.d.ts +0 -6
- package/dist/config.d.ts.map +0 -1
- package/dist/config.mjs +0 -29
- package/dist/config.mjs.map +0 -1
- package/src/__tests__/load-asset-config.test.ts +0 -121
- package/src/__tests__/scriptable-pack.test-d.ts +0 -131
- package/src/__tests__/scriptable-pack.unit.test.ts +0 -789
- package/src/config.ts +0 -36
package/dist/build.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { ok, err, catalogOperationsFor, authoringCapabilityForAssetKind,
|
|
2
|
-
import {
|
|
1
|
+
import { ok, err, catalogOperationsFor, authoringCapabilityForAssetKind, MATERIAL_TEXTURE_SLOTS, projectCookProductEvidence, projectAssetEvidence, validateSourceOverrideMap, PACK_ERROR_HINTS, catalogEntryDigest, AssetError, ImportError } from '@forgeax/engine-types';
|
|
2
|
+
import { dirname, resolve, isAbsolute, relative, join, basename, sep, extname } from 'path';
|
|
3
|
+
import { sha1 } from '@noble/hashes/legacy.js';
|
|
3
4
|
import { uuidv7obj } from 'uuidv7';
|
|
4
|
-
import { readFileSync, existsSync } from 'fs';
|
|
5
5
|
import { createHash } from 'crypto';
|
|
6
|
-
import { stat, readFile, readdir, realpath,
|
|
6
|
+
import { stat, readFile, readdir, realpath, mkdir, writeFile, rename, rm, mkdtemp } from 'fs/promises';
|
|
7
|
+
import { existsSync } from 'fs';
|
|
7
8
|
import { tmpdir } from 'os';
|
|
8
9
|
import { fileURLToPath } from 'url';
|
|
9
10
|
import { Worker } from 'worker_threads';
|
|
@@ -1300,21 +1301,21 @@ var require_errors = __commonJS({
|
|
|
1300
1301
|
function extendErrors({ gen, keyword, schemaValue, data, errsCount, it }) {
|
|
1301
1302
|
if (errsCount === void 0)
|
|
1302
1303
|
throw new Error("ajv implementation error");
|
|
1303
|
-
const
|
|
1304
|
+
const err8 = gen.name("err");
|
|
1304
1305
|
gen.forRange("i", errsCount, names_1.default.errors, (i) => {
|
|
1305
|
-
gen.const(
|
|
1306
|
-
gen.if((0, codegen_1._)`${
|
|
1307
|
-
gen.assign((0, codegen_1._)`${
|
|
1306
|
+
gen.const(err8, (0, codegen_1._)`${names_1.default.vErrors}[${i}]`);
|
|
1307
|
+
gen.if((0, codegen_1._)`${err8}.instancePath === undefined`, () => gen.assign((0, codegen_1._)`${err8}.instancePath`, (0, codegen_1.strConcat)(names_1.default.instancePath, it.errorPath)));
|
|
1308
|
+
gen.assign((0, codegen_1._)`${err8}.schemaPath`, (0, codegen_1.str)`${it.errSchemaPath}/${keyword}`);
|
|
1308
1309
|
if (it.opts.verbose) {
|
|
1309
|
-
gen.assign((0, codegen_1._)`${
|
|
1310
|
-
gen.assign((0, codegen_1._)`${
|
|
1310
|
+
gen.assign((0, codegen_1._)`${err8}.schema`, schemaValue);
|
|
1311
|
+
gen.assign((0, codegen_1._)`${err8}.data`, data);
|
|
1311
1312
|
}
|
|
1312
1313
|
});
|
|
1313
1314
|
}
|
|
1314
1315
|
exports.extendErrors = extendErrors;
|
|
1315
1316
|
function addError(gen, errObj) {
|
|
1316
|
-
const
|
|
1317
|
-
gen.if((0, codegen_1._)`${names_1.default.vErrors} === null`, () => gen.assign(names_1.default.vErrors, (0, codegen_1._)`[${
|
|
1317
|
+
const err8 = gen.const("err", errObj);
|
|
1318
|
+
gen.if((0, codegen_1._)`${names_1.default.vErrors} === null`, () => gen.assign(names_1.default.vErrors, (0, codegen_1._)`[${err8}]`), (0, codegen_1._)`${names_1.default.vErrors}.push(${err8})`);
|
|
1318
1319
|
gen.code((0, codegen_1._)`${names_1.default.errors}++`);
|
|
1319
1320
|
}
|
|
1320
1321
|
function returnErrors(it, errs) {
|
|
@@ -2966,7 +2967,7 @@ var require_compile = __commonJS({
|
|
|
2966
2967
|
const schOrFunc = root.refs[ref];
|
|
2967
2968
|
if (schOrFunc)
|
|
2968
2969
|
return schOrFunc;
|
|
2969
|
-
let _sch =
|
|
2970
|
+
let _sch = resolve4.call(this, root, ref);
|
|
2970
2971
|
if (_sch === void 0) {
|
|
2971
2972
|
const schema = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
|
|
2972
2973
|
const { schemaId } = this.opts;
|
|
@@ -2993,7 +2994,7 @@ var require_compile = __commonJS({
|
|
|
2993
2994
|
function sameSchemaEnv(s1, s2) {
|
|
2994
2995
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
2995
2996
|
}
|
|
2996
|
-
function
|
|
2997
|
+
function resolve4(root, ref) {
|
|
2997
2998
|
let sch;
|
|
2998
2999
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
2999
3000
|
ref = sch;
|
|
@@ -3621,7 +3622,7 @@ var require_fast_uri = __commonJS({
|
|
|
3621
3622
|
}
|
|
3622
3623
|
return uri;
|
|
3623
3624
|
}
|
|
3624
|
-
function
|
|
3625
|
+
function resolve4(baseURI, relativeURI, options) {
|
|
3625
3626
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3626
3627
|
const resolved = resolveComponent(parse(baseURI, schemelessOptions), parse(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
3627
3628
|
schemelessOptions.skipEscape = true;
|
|
@@ -3879,7 +3880,7 @@ var require_fast_uri = __commonJS({
|
|
|
3879
3880
|
var fastUri = {
|
|
3880
3881
|
SCHEMES,
|
|
3881
3882
|
normalize,
|
|
3882
|
-
resolve:
|
|
3883
|
+
resolve: resolve4,
|
|
3883
3884
|
resolveComponent,
|
|
3884
3885
|
equal,
|
|
3885
3886
|
serialize,
|
|
@@ -4716,8 +4717,8 @@ var require_multipleOf = __commonJS({
|
|
|
4716
4717
|
const { gen, data, schemaCode, it } = cxt;
|
|
4717
4718
|
const prec = it.opts.multipleOfPrecision;
|
|
4718
4719
|
const res = gen.let("res");
|
|
4719
|
-
const
|
|
4720
|
-
cxt.fail$data((0, codegen_1._)`(${schemaCode} === 0 || (${res} = ${data}/${schemaCode}, ${
|
|
4720
|
+
const invalid2 = prec ? (0, codegen_1._)`Math.abs(Math.round(${res}) - ${res}) > 1e-${prec}` : (0, codegen_1._)`${res} !== parseInt(${res})`;
|
|
4721
|
+
cxt.fail$data((0, codegen_1._)`(${schemaCode} === 0 || (${res} = ${data}/${schemaCode}, ${invalid2}))`);
|
|
4721
4722
|
}
|
|
4722
4723
|
};
|
|
4723
4724
|
exports.default = def;
|
|
@@ -6895,6 +6896,10 @@ function bytesToDashForm(bytes) {
|
|
|
6895
6896
|
return `${h[bytes[0]]}${h[bytes[1]]}${h[bytes[2]]}${h[bytes[3]]}-${h[bytes[4]]}${h[bytes[5]]}-${h[bytes[6]]}${h[bytes[7]]}-${h[bytes[8]]}${h[bytes[9]]}-${h[bytes[10]]}${h[bytes[11]]}${h[bytes[12]]}${h[bytes[13]]}${h[bytes[14]]}${h[bytes[15]]}`;
|
|
6896
6897
|
}
|
|
6897
6898
|
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
6899
|
+
var PACK_SOURCE_KEY_RE = /^[a-z0-9][a-z0-9._-]*(\/[a-z0-9][a-z0-9._-]*)*$/;
|
|
6900
|
+
function isValidPackSourceKey(value) {
|
|
6901
|
+
return typeof value === "string" && PACK_SOURCE_KEY_RE.test(value);
|
|
6902
|
+
}
|
|
6898
6903
|
function isValidAssetGuidString(value) {
|
|
6899
6904
|
return typeof value === "string" && UUID_RE.test(value);
|
|
6900
6905
|
}
|
|
@@ -6906,6 +6911,48 @@ function dashFormToBytes(dashForm) {
|
|
|
6906
6911
|
}
|
|
6907
6912
|
return bytes;
|
|
6908
6913
|
}
|
|
6914
|
+
function randomUuidBytes() {
|
|
6915
|
+
const uuid = uuidv7obj();
|
|
6916
|
+
const bytes = new Uint8Array(16);
|
|
6917
|
+
bytes.set(uuid.bytes);
|
|
6918
|
+
return bytes;
|
|
6919
|
+
}
|
|
6920
|
+
function packageId(value) {
|
|
6921
|
+
return value;
|
|
6922
|
+
}
|
|
6923
|
+
var PackageId = {
|
|
6924
|
+
parse(dashForm) {
|
|
6925
|
+
const parsed = AssetGuid.parse(dashForm);
|
|
6926
|
+
return parsed.ok ? { ok: true, value: packageId(parsed.value) } : parsed;
|
|
6927
|
+
},
|
|
6928
|
+
format(value) {
|
|
6929
|
+
return bytesToDashForm(value);
|
|
6930
|
+
},
|
|
6931
|
+
random() {
|
|
6932
|
+
return packageId(randomUuidBytes());
|
|
6933
|
+
}
|
|
6934
|
+
};
|
|
6935
|
+
function derivedGuid(namespace, sourceKey2) {
|
|
6936
|
+
if (!(namespace instanceof Uint8Array) || namespace.byteLength !== 16) {
|
|
6937
|
+
throw new TypeError("AssetGuid.derive requires a 16-byte PackageId");
|
|
6938
|
+
}
|
|
6939
|
+
if (!isValidPackSourceKey(sourceKey2)) {
|
|
6940
|
+
const error = new TypeError(
|
|
6941
|
+
`AssetGuid.derive received invalid sourceKey ${JSON.stringify(sourceKey2)}`
|
|
6942
|
+
);
|
|
6943
|
+
Object.defineProperty(error, "code", { value: "pack-source-key-invalid" });
|
|
6944
|
+
throw error;
|
|
6945
|
+
}
|
|
6946
|
+
const name = new TextEncoder().encode(sourceKey2);
|
|
6947
|
+
const input = new Uint8Array(namespace.byteLength + name.byteLength);
|
|
6948
|
+
input.set(namespace, 0);
|
|
6949
|
+
input.set(name, namespace.byteLength);
|
|
6950
|
+
const digest3 = sha1(input);
|
|
6951
|
+
const result = digest3.slice(0, 16);
|
|
6952
|
+
result[6] = (result[6] ?? 0) & 15 | 80;
|
|
6953
|
+
result[8] = (result[8] ?? 0) & 63 | 128;
|
|
6954
|
+
return brand(result);
|
|
6955
|
+
}
|
|
6909
6956
|
var AssetGuid = {
|
|
6910
6957
|
/**
|
|
6911
6958
|
* Parse a 36-char RFC 4122 dash-form UUID string into an AssetGuid.
|
|
@@ -6949,507 +6996,1075 @@ var AssetGuid = {
|
|
|
6949
6996
|
* Works in both Node.js and browser environments.
|
|
6950
6997
|
*/
|
|
6951
6998
|
random() {
|
|
6952
|
-
|
|
6953
|
-
|
|
6954
|
-
|
|
6955
|
-
|
|
6999
|
+
return brand(randomUuidBytes());
|
|
7000
|
+
},
|
|
7001
|
+
/** Derive the stable UUIDv5 projection for one Pack subject and sourceKey. */
|
|
7002
|
+
derive(namespace, sourceKey2) {
|
|
7003
|
+
return derivedGuid(namespace, sourceKey2);
|
|
6956
7004
|
}
|
|
6957
7005
|
};
|
|
6958
|
-
|
|
6959
|
-
|
|
6960
|
-
|
|
6961
|
-
"
|
|
6962
|
-
"
|
|
6963
|
-
"
|
|
6964
|
-
"
|
|
6965
|
-
"
|
|
6966
|
-
"
|
|
6967
|
-
"
|
|
6968
|
-
"
|
|
6969
|
-
"
|
|
6970
|
-
"
|
|
6971
|
-
"skeleton",
|
|
6972
|
-
"skin",
|
|
6973
|
-
"animation-clip",
|
|
6974
|
-
"animation-graph",
|
|
6975
|
-
"audio",
|
|
6976
|
-
"particle-effect"
|
|
7006
|
+
var PACK_PARAMETER_TYPES = [
|
|
7007
|
+
"bool",
|
|
7008
|
+
"u32",
|
|
7009
|
+
"i32",
|
|
7010
|
+
"f32",
|
|
7011
|
+
"f64",
|
|
7012
|
+
"string",
|
|
7013
|
+
"enum",
|
|
7014
|
+
"vec2",
|
|
7015
|
+
"vec3",
|
|
7016
|
+
"vec4",
|
|
7017
|
+
"color",
|
|
7018
|
+
"asset-guid"
|
|
6977
7019
|
];
|
|
6978
|
-
|
|
6979
|
-
assetKinds: SCRIPTABLE_PACK_ASSET_KINDS,
|
|
6980
|
-
durablePayload: true,
|
|
6981
|
-
refs: true,
|
|
6982
|
-
artifacts: true,
|
|
6983
|
-
hostCapabilities: ["audio-install", "video-play", "particle-execute"]
|
|
6984
|
-
};
|
|
6985
|
-
function isScriptablePackAssetKind(value) {
|
|
6986
|
-
return SCRIPTABLE_PACK_ASSET_KINDS.includes(value);
|
|
6987
|
-
}
|
|
6988
|
-
function sceneComponentFieldType(value) {
|
|
6989
|
-
if (typeof value === "string") return value;
|
|
6990
|
-
if (isRecord(value) && typeof value.type === "string") return value.type;
|
|
6991
|
-
return void 0;
|
|
6992
|
-
}
|
|
6993
|
-
function projectScriptablePackSceneComponents(components) {
|
|
6994
|
-
return (components ?? []).map((component) => ({
|
|
6995
|
-
name: component.name,
|
|
6996
|
-
fields: Object.fromEntries(
|
|
6997
|
-
Object.entries(component.fields).map(([fieldName, field]) => [
|
|
6998
|
-
fieldName,
|
|
6999
|
-
sceneComponentFieldType(field)
|
|
7000
|
-
])
|
|
7001
|
-
)
|
|
7002
|
-
}));
|
|
7003
|
-
}
|
|
7004
|
-
var SCRIPTABLE_PACK_REQUEST_ID_SCHEMA = {
|
|
7005
|
-
type: "string",
|
|
7006
|
-
minLength: 1,
|
|
7007
|
-
maxLength: 128,
|
|
7008
|
-
pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$",
|
|
7009
|
-
description: "Caller-minted identity for one idempotent ScriptablePack operation."
|
|
7010
|
-
};
|
|
7011
|
-
var SCRIPTABLE_PACK_SOURCE_PATH_SCHEMA = {
|
|
7012
|
-
type: "string",
|
|
7013
|
-
minLength: 8,
|
|
7014
|
-
pattern: "^[^/].*\\.pack\\.ts$",
|
|
7015
|
-
description: "Game-root-relative ScriptablePack source path."
|
|
7016
|
-
};
|
|
7017
|
-
var SCRIPTABLE_PACK_OWNER_GUID_SCHEMA = {
|
|
7018
|
-
type: "string",
|
|
7019
|
-
format: "uuid",
|
|
7020
|
-
description: "Catalog GUID used to resolve the producer-owned source subject."
|
|
7021
|
-
};
|
|
7022
|
-
var SCRIPTABLE_PACK_REVISION_SCHEMA = {
|
|
7023
|
-
type: "string",
|
|
7024
|
-
minLength: 64,
|
|
7025
|
-
maxLength: 64,
|
|
7026
|
-
pattern: "^[a-f0-9]{64}$",
|
|
7027
|
-
description: "SHA-256 source revision returned by preflight."
|
|
7028
|
-
};
|
|
7029
|
-
var SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA = { type: "string", minLength: 1 };
|
|
7030
|
-
var SCRIPTABLE_PACK_ASSET_KIND_SCHEMA = {
|
|
7031
|
-
enum: SCRIPTABLE_PACK_ASSET_KINDS,
|
|
7032
|
-
description: "Ordinary Asset kind supported by the ScriptablePack producer/loader matrix."
|
|
7033
|
-
};
|
|
7034
|
-
var SCRIPTABLE_PACK_NAME_SCHEMA = { type: "string", minLength: 1 };
|
|
7035
|
-
function scriptablePackArgsSchema(properties, required, options = {}) {
|
|
7036
|
-
const subjectRequired = ["requestId", ...required];
|
|
7020
|
+
function authoringError(code, expected, hint, detail = {}, actual) {
|
|
7037
7021
|
return {
|
|
7038
|
-
|
|
7039
|
-
|
|
7040
|
-
|
|
7041
|
-
|
|
7042
|
-
|
|
7043
|
-
...properties
|
|
7044
|
-
},
|
|
7045
|
-
required: subjectRequired,
|
|
7046
|
-
...options.subject === false ? {} : {
|
|
7047
|
-
anyOf: [
|
|
7048
|
-
{ required: [...subjectRequired, "sourcePath"] },
|
|
7049
|
-
{ required: [...subjectRequired, "ownerGuid"] },
|
|
7050
|
-
...options.guidSubject === false ? [] : [{ required: [...subjectRequired, "guid"] }]
|
|
7051
|
-
]
|
|
7052
|
-
},
|
|
7053
|
-
additionalProperties: false
|
|
7022
|
+
code,
|
|
7023
|
+
expected,
|
|
7024
|
+
hint,
|
|
7025
|
+
...actual === void 0 ? {} : { actual },
|
|
7026
|
+
detail
|
|
7054
7027
|
};
|
|
7055
7028
|
}
|
|
7056
|
-
|
|
7057
|
-
|
|
7058
|
-
id: "asset-source.create",
|
|
7059
|
-
kind: "create",
|
|
7060
|
-
domain: "session",
|
|
7061
|
-
title: "Create Asset Source",
|
|
7062
|
-
argsSchema: scriptablePackArgsSchema(
|
|
7063
|
-
{
|
|
7064
|
-
name: SCRIPTABLE_PACK_NAME_SCHEMA,
|
|
7065
|
-
initialOutput: {
|
|
7066
|
-
type: "object",
|
|
7067
|
-
properties: {
|
|
7068
|
-
sourceKey: SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA,
|
|
7069
|
-
kind: SCRIPTABLE_PACK_ASSET_KIND_SCHEMA,
|
|
7070
|
-
name: SCRIPTABLE_PACK_NAME_SCHEMA
|
|
7071
|
-
},
|
|
7072
|
-
required: ["sourceKey", "kind"],
|
|
7073
|
-
additionalProperties: false
|
|
7074
|
-
}
|
|
7075
|
-
},
|
|
7076
|
-
["sourcePath", "initialOutput"],
|
|
7077
|
-
{ subject: false }
|
|
7078
|
-
)
|
|
7079
|
-
},
|
|
7080
|
-
{
|
|
7081
|
-
id: "asset-source.add-output",
|
|
7082
|
-
kind: "add-output",
|
|
7083
|
-
domain: "session",
|
|
7084
|
-
title: "Add Asset Source Output",
|
|
7085
|
-
argsSchema: scriptablePackArgsSchema(
|
|
7086
|
-
{
|
|
7087
|
-
sourceKey: SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA,
|
|
7088
|
-
assetKind: SCRIPTABLE_PACK_ASSET_KIND_SCHEMA,
|
|
7089
|
-
name: SCRIPTABLE_PACK_NAME_SCHEMA,
|
|
7090
|
-
expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA
|
|
7091
|
-
},
|
|
7092
|
-
["sourceKey", "assetKind", "expectedRevision"]
|
|
7093
|
-
)
|
|
7094
|
-
},
|
|
7095
|
-
{
|
|
7096
|
-
id: "asset-source.add-external-asset",
|
|
7097
|
-
kind: "add-external-asset",
|
|
7098
|
-
domain: "session",
|
|
7099
|
-
title: "Add Asset Source External Asset",
|
|
7100
|
-
argsSchema: scriptablePackArgsSchema(
|
|
7101
|
-
{
|
|
7102
|
-
alias: SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA,
|
|
7103
|
-
guid: { type: "string", format: "uuid" },
|
|
7104
|
-
expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA
|
|
7105
|
-
},
|
|
7106
|
-
["alias", "guid", "expectedRevision"],
|
|
7107
|
-
{ guidSubject: false }
|
|
7108
|
-
)
|
|
7109
|
-
},
|
|
7110
|
-
{
|
|
7111
|
-
id: "asset-source.rename",
|
|
7112
|
-
kind: "rename",
|
|
7113
|
-
domain: "session",
|
|
7114
|
-
title: "Rename Asset Source Display Name",
|
|
7115
|
-
argsSchema: scriptablePackArgsSchema(
|
|
7116
|
-
{
|
|
7117
|
-
target: {
|
|
7118
|
-
oneOf: [
|
|
7119
|
-
{
|
|
7120
|
-
type: "object",
|
|
7121
|
-
properties: { kind: { const: "package" } },
|
|
7122
|
-
required: ["kind"],
|
|
7123
|
-
additionalProperties: false
|
|
7124
|
-
},
|
|
7125
|
-
{
|
|
7126
|
-
type: "object",
|
|
7127
|
-
properties: {
|
|
7128
|
-
kind: { const: "output" },
|
|
7129
|
-
sourceKey: SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA
|
|
7130
|
-
},
|
|
7131
|
-
required: ["kind", "sourceKey"],
|
|
7132
|
-
additionalProperties: false
|
|
7133
|
-
}
|
|
7134
|
-
]
|
|
7135
|
-
},
|
|
7136
|
-
name: SCRIPTABLE_PACK_NAME_SCHEMA,
|
|
7137
|
-
expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA
|
|
7138
|
-
},
|
|
7139
|
-
["target", "name", "expectedRevision"]
|
|
7140
|
-
)
|
|
7141
|
-
},
|
|
7142
|
-
{
|
|
7143
|
-
id: "asset-source.remove-output",
|
|
7144
|
-
kind: "remove-output",
|
|
7145
|
-
domain: "session",
|
|
7146
|
-
title: "Remove Asset Source Output",
|
|
7147
|
-
destructive: true,
|
|
7148
|
-
argsSchema: scriptablePackArgsSchema(
|
|
7149
|
-
{
|
|
7150
|
-
sourceKey: SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA,
|
|
7151
|
-
confirmIncomingRefs: { type: "array", items: { type: "string" } },
|
|
7152
|
-
expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA
|
|
7153
|
-
},
|
|
7154
|
-
["sourceKey", "expectedRevision"]
|
|
7155
|
-
)
|
|
7156
|
-
},
|
|
7157
|
-
{
|
|
7158
|
-
id: "asset-source.clone",
|
|
7159
|
-
kind: "clone",
|
|
7160
|
-
domain: "session",
|
|
7161
|
-
title: "Clone Asset Source",
|
|
7162
|
-
argsSchema: scriptablePackArgsSchema(
|
|
7163
|
-
{
|
|
7164
|
-
targetPath: SCRIPTABLE_PACK_SOURCE_PATH_SCHEMA,
|
|
7165
|
-
expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA
|
|
7166
|
-
},
|
|
7167
|
-
["targetPath", "expectedRevision"]
|
|
7168
|
-
)
|
|
7169
|
-
},
|
|
7170
|
-
{
|
|
7171
|
-
id: "asset-source.rebuild",
|
|
7172
|
-
kind: "rebuild",
|
|
7173
|
-
domain: "session",
|
|
7174
|
-
title: "Rebuild Asset Source",
|
|
7175
|
-
argsSchema: scriptablePackArgsSchema({ expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA }, [
|
|
7176
|
-
"expectedRevision"
|
|
7177
|
-
])
|
|
7178
|
-
},
|
|
7179
|
-
{
|
|
7180
|
-
id: "asset-source.cold-cook",
|
|
7181
|
-
kind: "cold-cook",
|
|
7182
|
-
domain: "session",
|
|
7183
|
-
title: "Cold Cook Asset Source",
|
|
7184
|
-
argsSchema: scriptablePackArgsSchema({ expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA }, [
|
|
7185
|
-
"expectedRevision"
|
|
7186
|
-
])
|
|
7187
|
-
}
|
|
7188
|
-
];
|
|
7189
|
-
function actual(value) {
|
|
7190
|
-
if (value === null) return "null";
|
|
7191
|
-
if (Array.isArray(value)) return "array";
|
|
7192
|
-
if (ArrayBuffer.isView(value)) return value.constructor.name;
|
|
7193
|
-
return typeof value;
|
|
7194
|
-
}
|
|
7195
|
-
function invalid(propertyPath, expected, value, sourcePath) {
|
|
7196
|
-
return err({
|
|
7197
|
-
code: "pack-source-definition-invalid",
|
|
7198
|
-
expected,
|
|
7199
|
-
hint: "repair the default exported ScriptablePack definition, then inspect Meta again",
|
|
7200
|
-
detail: {
|
|
7201
|
-
...sourcePath === void 0 ? {} : { sourcePath },
|
|
7202
|
-
propertyPath,
|
|
7203
|
-
actual: actual(value)
|
|
7204
|
-
}
|
|
7205
|
-
});
|
|
7029
|
+
function failure(error) {
|
|
7030
|
+
return err(error);
|
|
7206
7031
|
}
|
|
7207
7032
|
function isRecord(value) {
|
|
7208
7033
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
7209
7034
|
}
|
|
7210
|
-
function
|
|
7035
|
+
function validateSceneComponents(value) {
|
|
7036
|
+
if (value === void 0) return ok(void 0);
|
|
7037
|
+
if (!Array.isArray(value)) {
|
|
7038
|
+
return failure(
|
|
7039
|
+
parameterFailure(
|
|
7040
|
+
"$.sceneComponents",
|
|
7041
|
+
"an array of component schema records",
|
|
7042
|
+
value,
|
|
7043
|
+
"sceneComponents is not an array"
|
|
7044
|
+
)
|
|
7045
|
+
);
|
|
7046
|
+
}
|
|
7047
|
+
const components = [];
|
|
7048
|
+
const names = /* @__PURE__ */ new Set();
|
|
7049
|
+
for (const [componentIndex, candidate] of value.entries()) {
|
|
7050
|
+
if (!isRecord(candidate) || typeof candidate.name !== "string" || !isRecord(candidate.fields)) {
|
|
7051
|
+
return failure(
|
|
7052
|
+
parameterFailure(
|
|
7053
|
+
`$.sceneComponents[${componentIndex}]`,
|
|
7054
|
+
"a component record with name and fields",
|
|
7055
|
+
candidate,
|
|
7056
|
+
"scene component schema is malformed"
|
|
7057
|
+
)
|
|
7058
|
+
);
|
|
7059
|
+
}
|
|
7060
|
+
if (candidate.name.length === 0 || names.has(candidate.name)) {
|
|
7061
|
+
return failure(
|
|
7062
|
+
parameterFailure(
|
|
7063
|
+
`$.sceneComponents[${componentIndex}].name`,
|
|
7064
|
+
"a non-empty unique component name",
|
|
7065
|
+
candidate.name,
|
|
7066
|
+
"scene component names must be unique"
|
|
7067
|
+
)
|
|
7068
|
+
);
|
|
7069
|
+
}
|
|
7070
|
+
names.add(candidate.name);
|
|
7071
|
+
const fields = {};
|
|
7072
|
+
for (const [fieldName, field] of Object.entries(candidate.fields)) {
|
|
7073
|
+
if (typeof field === "string" && field.length === 0 || typeof field !== "string" && (!isRecord(field) || typeof field.type !== "string" || field.type.length === 0)) {
|
|
7074
|
+
return failure(
|
|
7075
|
+
parameterFailure(
|
|
7076
|
+
`$.sceneComponents[${componentIndex}].fields.${fieldName}`,
|
|
7077
|
+
"a field type string or { type: string }",
|
|
7078
|
+
field,
|
|
7079
|
+
"scene component field schema is malformed"
|
|
7080
|
+
)
|
|
7081
|
+
);
|
|
7082
|
+
}
|
|
7083
|
+
fields[fieldName] = field;
|
|
7084
|
+
}
|
|
7085
|
+
components.push({ name: candidate.name, fields });
|
|
7086
|
+
}
|
|
7087
|
+
return ok(components);
|
|
7088
|
+
}
|
|
7089
|
+
function isPackageId(value) {
|
|
7211
7090
|
return value instanceof Uint8Array && value.byteLength === 16;
|
|
7212
7091
|
}
|
|
7213
|
-
function
|
|
7214
|
-
return
|
|
7092
|
+
function cloneValue(value) {
|
|
7093
|
+
if (value instanceof Uint8Array) return value.slice();
|
|
7094
|
+
if (Array.isArray(value)) return value.map((item) => cloneValue(item));
|
|
7095
|
+
return value;
|
|
7215
7096
|
}
|
|
7216
|
-
function
|
|
7217
|
-
|
|
7218
|
-
|
|
7219
|
-
|
|
7220
|
-
|
|
7221
|
-
|
|
7222
|
-
|
|
7223
|
-
const externalAssets = Object.fromEntries(
|
|
7224
|
-
Object.entries(definition.externalAssets).map(([alias, guid]) => [
|
|
7225
|
-
alias,
|
|
7226
|
-
guid.slice()
|
|
7227
|
-
])
|
|
7097
|
+
function sourceKeyFailure(sourceKey2, propertyPath = "$.sourceKey") {
|
|
7098
|
+
return authoringError(
|
|
7099
|
+
"pack-source-key-invalid",
|
|
7100
|
+
"a sourceKey matching ^[a-z0-9][a-z0-9._-]*(/[a-z0-9][a-z0-9._-]*)*$",
|
|
7101
|
+
"use a stable lower-case semantic key; do not derive it from file paths or output order",
|
|
7102
|
+
{ propertyPath, sourceKey: sourceKey2 },
|
|
7103
|
+
typeof sourceKey2 === "string" ? sourceKey2 : void 0
|
|
7228
7104
|
);
|
|
7229
|
-
|
|
7230
|
-
|
|
7231
|
-
|
|
7232
|
-
|
|
7233
|
-
|
|
7234
|
-
|
|
7235
|
-
)
|
|
7105
|
+
}
|
|
7106
|
+
function parameterFailure(propertyPath, expected, actual, reason) {
|
|
7107
|
+
return authoringError(
|
|
7108
|
+
"pack-parameter-invalid",
|
|
7109
|
+
expected,
|
|
7110
|
+
"repair the parameter declaration or the instance values, then inspect and rebuild",
|
|
7111
|
+
{ propertyPath, reason, actual: typeof actual === "string" ? actual : JSON.stringify(actual) }
|
|
7236
7112
|
);
|
|
7237
|
-
return Object.freeze({
|
|
7238
|
-
...definition,
|
|
7239
|
-
packageId: definition.packageId.slice(),
|
|
7240
|
-
assets: Object.freeze(assets),
|
|
7241
|
-
externalAssets: Object.freeze(externalAssets),
|
|
7242
|
-
...sceneComponents === void 0 ? {} : { sceneComponents }
|
|
7243
|
-
});
|
|
7244
7113
|
}
|
|
7245
|
-
function
|
|
7246
|
-
|
|
7247
|
-
|
|
7248
|
-
|
|
7249
|
-
|
|
7114
|
+
function numericType(type) {
|
|
7115
|
+
return type === "u32" || type === "i32" || type === "f32" || type === "f64";
|
|
7116
|
+
}
|
|
7117
|
+
function vectorLength(type) {
|
|
7118
|
+
switch (type) {
|
|
7119
|
+
case "vec2":
|
|
7120
|
+
return 2;
|
|
7121
|
+
case "vec3":
|
|
7122
|
+
return 3;
|
|
7123
|
+
case "vec4":
|
|
7124
|
+
case "color":
|
|
7125
|
+
return 4;
|
|
7126
|
+
default:
|
|
7127
|
+
return void 0;
|
|
7250
7128
|
}
|
|
7251
|
-
|
|
7252
|
-
|
|
7129
|
+
}
|
|
7130
|
+
function parameterValueError(parameter, value, propertyPath) {
|
|
7131
|
+
const { type } = parameter;
|
|
7132
|
+
if (type === "bool" && typeof value !== "boolean") {
|
|
7133
|
+
return parameterFailure(propertyPath, "a boolean", value, "bool value has the wrong type");
|
|
7134
|
+
}
|
|
7135
|
+
if (numericType(type)) {
|
|
7136
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
7137
|
+
return parameterFailure(
|
|
7138
|
+
propertyPath,
|
|
7139
|
+
"a finite number",
|
|
7140
|
+
value,
|
|
7141
|
+
"numeric value is not finite"
|
|
7142
|
+
);
|
|
7143
|
+
}
|
|
7144
|
+
if ((type === "u32" || type === "i32") && !Number.isInteger(value)) {
|
|
7145
|
+
return parameterFailure(
|
|
7146
|
+
propertyPath,
|
|
7147
|
+
"an integer",
|
|
7148
|
+
value,
|
|
7149
|
+
"integer parameter received a fraction"
|
|
7150
|
+
);
|
|
7151
|
+
}
|
|
7152
|
+
if (type === "u32" && (value < 0 || value > 4294967295)) {
|
|
7153
|
+
return parameterFailure(
|
|
7154
|
+
propertyPath,
|
|
7155
|
+
"an unsigned 32-bit integer",
|
|
7156
|
+
value,
|
|
7157
|
+
"u32 value is outside [0, 2^32 - 1]"
|
|
7158
|
+
);
|
|
7159
|
+
}
|
|
7160
|
+
if (type === "i32" && (value < -2147483648 || value > 2147483647)) {
|
|
7161
|
+
return parameterFailure(
|
|
7162
|
+
propertyPath,
|
|
7163
|
+
"a signed 32-bit integer",
|
|
7164
|
+
value,
|
|
7165
|
+
"i32 value is outside [-2^31, 2^31 - 1]"
|
|
7166
|
+
);
|
|
7167
|
+
}
|
|
7168
|
+
if (type === "f32" && !Number.isFinite(Math.fround(value))) {
|
|
7169
|
+
return parameterFailure(
|
|
7170
|
+
propertyPath,
|
|
7171
|
+
"a finite IEEE-754 32-bit float",
|
|
7172
|
+
value,
|
|
7173
|
+
"f32 value overflows binary32"
|
|
7174
|
+
);
|
|
7175
|
+
}
|
|
7176
|
+
if (parameter.minimum !== void 0 && value < parameter.minimum) {
|
|
7177
|
+
return parameterFailure(
|
|
7178
|
+
propertyPath,
|
|
7179
|
+
`a number >= ${parameter.minimum}`,
|
|
7180
|
+
value,
|
|
7181
|
+
"value is below minimum"
|
|
7182
|
+
);
|
|
7183
|
+
}
|
|
7184
|
+
if (parameter.maximum !== void 0 && value > parameter.maximum) {
|
|
7185
|
+
return parameterFailure(
|
|
7186
|
+
propertyPath,
|
|
7187
|
+
`a number <= ${parameter.maximum}`,
|
|
7188
|
+
value,
|
|
7189
|
+
"value is above maximum"
|
|
7190
|
+
);
|
|
7191
|
+
}
|
|
7192
|
+
return void 0;
|
|
7253
7193
|
}
|
|
7254
|
-
if (
|
|
7255
|
-
return
|
|
7256
|
-
}
|
|
7257
|
-
if (!isRecord(value.assets) || Object.keys(value.assets).length === 0) {
|
|
7258
|
-
return invalid(
|
|
7259
|
-
"$.assets",
|
|
7260
|
-
"a non-empty sourceKey to descriptor object",
|
|
7261
|
-
value.assets,
|
|
7262
|
-
sourcePath
|
|
7263
|
-
);
|
|
7194
|
+
if (type === "string" && typeof value !== "string") {
|
|
7195
|
+
return parameterFailure(propertyPath, "a string", value, "string parameter has the wrong type");
|
|
7264
7196
|
}
|
|
7265
|
-
if (
|
|
7266
|
-
|
|
7267
|
-
|
|
7268
|
-
|
|
7269
|
-
|
|
7270
|
-
|
|
7271
|
-
|
|
7197
|
+
if (type === "enum") {
|
|
7198
|
+
if (typeof value !== "string") {
|
|
7199
|
+
return parameterFailure(
|
|
7200
|
+
propertyPath,
|
|
7201
|
+
"one of the declared enum strings",
|
|
7202
|
+
value,
|
|
7203
|
+
"enum value has the wrong type"
|
|
7204
|
+
);
|
|
7205
|
+
}
|
|
7206
|
+
if (parameter.values === void 0 || !parameter.values.includes(value)) {
|
|
7207
|
+
return parameterFailure(
|
|
7208
|
+
propertyPath,
|
|
7209
|
+
"one of the declared enum values",
|
|
7210
|
+
value,
|
|
7211
|
+
"enum value is not declared"
|
|
7212
|
+
);
|
|
7213
|
+
}
|
|
7214
|
+
return void 0;
|
|
7272
7215
|
}
|
|
7273
|
-
|
|
7274
|
-
|
|
7275
|
-
|
|
7276
|
-
|
|
7277
|
-
|
|
7278
|
-
|
|
7279
|
-
|
|
7216
|
+
const length = vectorLength(type);
|
|
7217
|
+
if (length !== void 0) {
|
|
7218
|
+
if (!Array.isArray(value) || value.length !== length || value.some((component) => typeof component !== "number" || !Number.isFinite(component))) {
|
|
7219
|
+
return parameterFailure(
|
|
7220
|
+
propertyPath,
|
|
7221
|
+
`a finite numeric vector with ${length} components`,
|
|
7222
|
+
value,
|
|
7223
|
+
"vector value has the wrong shape"
|
|
7280
7224
|
);
|
|
7281
7225
|
}
|
|
7282
|
-
|
|
7283
|
-
|
|
7284
|
-
|
|
7285
|
-
|
|
7286
|
-
|
|
7287
|
-
|
|
7288
|
-
|
|
7289
|
-
sourcePath
|
|
7290
|
-
);
|
|
7291
|
-
}
|
|
7292
|
-
if (typeof component.name !== "string" || component.name.trim().length === 0) {
|
|
7293
|
-
return invalid(
|
|
7294
|
-
`$.sceneComponents[${componentIndex}].name`,
|
|
7295
|
-
"a non-empty component name",
|
|
7296
|
-
component.name,
|
|
7297
|
-
sourcePath
|
|
7298
|
-
);
|
|
7299
|
-
}
|
|
7300
|
-
if (componentNames.has(component.name)) {
|
|
7301
|
-
return invalid(
|
|
7302
|
-
`$.sceneComponents[${componentIndex}].name`,
|
|
7303
|
-
"component names to be unique within one ScriptablePack",
|
|
7304
|
-
component.name,
|
|
7305
|
-
sourcePath
|
|
7306
|
-
);
|
|
7307
|
-
}
|
|
7308
|
-
componentNames.add(component.name);
|
|
7309
|
-
if (!isRecord(component.fields)) {
|
|
7310
|
-
return invalid(
|
|
7311
|
-
`$.sceneComponents[${componentIndex}].fields`,
|
|
7312
|
-
"a field-name to schema-type object",
|
|
7313
|
-
component.fields,
|
|
7314
|
-
sourcePath
|
|
7315
|
-
);
|
|
7316
|
-
}
|
|
7317
|
-
for (const [fieldName, field] of Object.entries(component.fields)) {
|
|
7318
|
-
const type = sceneComponentFieldType(field);
|
|
7319
|
-
if (fieldName.trim().length === 0 || type === void 0 || type.trim().length === 0) {
|
|
7320
|
-
return invalid(
|
|
7321
|
-
`$.sceneComponents[${componentIndex}].fields`,
|
|
7322
|
-
"field names with non-empty string schema types",
|
|
7323
|
-
field,
|
|
7324
|
-
sourcePath
|
|
7325
|
-
);
|
|
7326
|
-
}
|
|
7327
|
-
}
|
|
7226
|
+
if (type === "color" && value.some((component) => component < 0 || component > 1)) {
|
|
7227
|
+
return parameterFailure(
|
|
7228
|
+
propertyPath,
|
|
7229
|
+
"an RGBA color with components in [0, 1]",
|
|
7230
|
+
value,
|
|
7231
|
+
"color component is outside [0, 1]"
|
|
7232
|
+
);
|
|
7328
7233
|
}
|
|
7234
|
+
return void 0;
|
|
7329
7235
|
}
|
|
7330
|
-
if (
|
|
7331
|
-
|
|
7332
|
-
|
|
7333
|
-
|
|
7334
|
-
|
|
7335
|
-
|
|
7336
|
-
|
|
7337
|
-
|
|
7338
|
-
|
|
7339
|
-
|
|
7340
|
-
|
|
7341
|
-
|
|
7342
|
-
|
|
7343
|
-
|
|
7344
|
-
|
|
7236
|
+
if (type === "asset-guid") {
|
|
7237
|
+
const validString = typeof value === "string" && isValidAssetGuidString(value);
|
|
7238
|
+
if (!(value instanceof Uint8Array && value.byteLength === 16) && !validString) {
|
|
7239
|
+
return parameterFailure(
|
|
7240
|
+
propertyPath,
|
|
7241
|
+
"a 16-byte AssetGuid or UUID string",
|
|
7242
|
+
value,
|
|
7243
|
+
"asset GUID value is malformed"
|
|
7244
|
+
);
|
|
7245
|
+
}
|
|
7246
|
+
return void 0;
|
|
7247
|
+
}
|
|
7248
|
+
return parameterFailure(
|
|
7249
|
+
propertyPath,
|
|
7250
|
+
"a supported Pack parameter type",
|
|
7251
|
+
value,
|
|
7252
|
+
"unknown parameter type"
|
|
7253
|
+
);
|
|
7254
|
+
}
|
|
7255
|
+
function normalizeParameterValue(parameter, value, propertyPath) {
|
|
7256
|
+
const error = parameterValueError(parameter, value, propertyPath);
|
|
7257
|
+
if (error !== void 0) return failure(error);
|
|
7258
|
+
if (parameter.type === "asset-guid" && typeof value === "string") {
|
|
7259
|
+
const parsed = AssetGuid.parse(value);
|
|
7260
|
+
if (!parsed.ok) {
|
|
7261
|
+
return failure(
|
|
7262
|
+
parameterFailure(
|
|
7263
|
+
propertyPath,
|
|
7264
|
+
"a valid AssetGuid UUID string",
|
|
7265
|
+
value,
|
|
7266
|
+
"asset GUID parser rejected the value"
|
|
7267
|
+
)
|
|
7345
7268
|
);
|
|
7346
7269
|
}
|
|
7347
|
-
|
|
7348
|
-
|
|
7349
|
-
|
|
7350
|
-
|
|
7351
|
-
|
|
7352
|
-
|
|
7270
|
+
return ok(parsed.value);
|
|
7271
|
+
}
|
|
7272
|
+
return ok(cloneValue(value));
|
|
7273
|
+
}
|
|
7274
|
+
function validateParameterDefinitions(parameters, propertyPath = "$.parameters") {
|
|
7275
|
+
if (!Array.isArray(parameters) || parameters.length === 0) {
|
|
7276
|
+
return failure(
|
|
7277
|
+
parameterFailure(
|
|
7278
|
+
propertyPath,
|
|
7279
|
+
"a non-empty parameter descriptor array",
|
|
7280
|
+
parameters,
|
|
7281
|
+
"parameters must be explicit and non-empty"
|
|
7282
|
+
)
|
|
7283
|
+
);
|
|
7284
|
+
}
|
|
7285
|
+
const names = /* @__PURE__ */ new Set();
|
|
7286
|
+
const normalized = [];
|
|
7287
|
+
for (const [index, candidate] of parameters.entries()) {
|
|
7288
|
+
const path = `${propertyPath}[${index}]`;
|
|
7289
|
+
if (!isRecord(candidate))
|
|
7290
|
+
return failure(
|
|
7291
|
+
parameterFailure(
|
|
7292
|
+
path,
|
|
7293
|
+
"a parameter descriptor object",
|
|
7294
|
+
candidate,
|
|
7295
|
+
"descriptor is not an object"
|
|
7296
|
+
)
|
|
7297
|
+
);
|
|
7298
|
+
const name = candidate.name;
|
|
7299
|
+
if (typeof name !== "string" || !/^[A-Za-z][A-Za-z0-9_.-]*$/.test(name)) {
|
|
7300
|
+
return failure(
|
|
7301
|
+
parameterFailure(
|
|
7302
|
+
`${path}.name`,
|
|
7303
|
+
"a unique identifier-like parameter name",
|
|
7304
|
+
name,
|
|
7305
|
+
"parameter name is invalid"
|
|
7306
|
+
)
|
|
7353
7307
|
);
|
|
7354
7308
|
}
|
|
7355
|
-
if (
|
|
7356
|
-
return
|
|
7357
|
-
|
|
7358
|
-
|
|
7359
|
-
|
|
7360
|
-
|
|
7309
|
+
if (names.has(name))
|
|
7310
|
+
return failure(
|
|
7311
|
+
parameterFailure(
|
|
7312
|
+
`${path}.name`,
|
|
7313
|
+
"a unique parameter name",
|
|
7314
|
+
name,
|
|
7315
|
+
"parameter name is duplicated"
|
|
7316
|
+
)
|
|
7317
|
+
);
|
|
7318
|
+
names.add(name);
|
|
7319
|
+
const unknown = Object.keys(candidate).find(
|
|
7320
|
+
(key) => !["name", "type", "default", "minimum", "maximum", "values", "kind"].includes(key)
|
|
7321
|
+
);
|
|
7322
|
+
if (unknown !== void 0) {
|
|
7323
|
+
return failure(
|
|
7324
|
+
parameterFailure(
|
|
7325
|
+
`${path}.${unknown}`,
|
|
7326
|
+
"only name, type, default, minimum, maximum, values, and kind fields",
|
|
7327
|
+
candidate[unknown],
|
|
7328
|
+
"parameter descriptors are a closed authoring schema"
|
|
7329
|
+
)
|
|
7330
|
+
);
|
|
7331
|
+
}
|
|
7332
|
+
const type = candidate.type;
|
|
7333
|
+
if (typeof type !== "string" || !PACK_PARAMETER_TYPES.includes(type)) {
|
|
7334
|
+
return failure(
|
|
7335
|
+
parameterFailure(
|
|
7336
|
+
`${path}.type`,
|
|
7337
|
+
PACK_PARAMETER_TYPES.join(" | "),
|
|
7338
|
+
type,
|
|
7339
|
+
"parameter type is not supported"
|
|
7340
|
+
)
|
|
7361
7341
|
);
|
|
7362
7342
|
}
|
|
7363
|
-
|
|
7364
|
-
|
|
7365
|
-
|
|
7366
|
-
|
|
7367
|
-
|
|
7368
|
-
|
|
7343
|
+
const typed = {
|
|
7344
|
+
...candidate,
|
|
7345
|
+
name,
|
|
7346
|
+
type
|
|
7347
|
+
};
|
|
7348
|
+
if (typed.values !== void 0) {
|
|
7349
|
+
if (typed.type !== "enum" || !Array.isArray(typed.values) || typed.values.length === 0 || typed.values.some((item) => typeof item !== "string") || new Set(typed.values).size !== typed.values.length) {
|
|
7350
|
+
return failure(
|
|
7351
|
+
parameterFailure(
|
|
7352
|
+
`${path}.values`,
|
|
7353
|
+
"unique non-empty strings for enum",
|
|
7354
|
+
typed.values,
|
|
7355
|
+
"enum values are malformed"
|
|
7356
|
+
)
|
|
7357
|
+
);
|
|
7358
|
+
}
|
|
7359
|
+
} else if (typed.type === "enum") {
|
|
7360
|
+
return failure(
|
|
7361
|
+
parameterFailure(
|
|
7362
|
+
`${path}.values`,
|
|
7363
|
+
"a non-empty enum choices array",
|
|
7364
|
+
typed.values,
|
|
7365
|
+
"enum has no choices"
|
|
7366
|
+
)
|
|
7369
7367
|
);
|
|
7370
7368
|
}
|
|
7371
|
-
|
|
7372
|
-
|
|
7373
|
-
|
|
7374
|
-
|
|
7375
|
-
|
|
7376
|
-
|
|
7377
|
-
|
|
7369
|
+
if (typed.kind !== void 0 && (typed.type !== "asset-guid" || typeof typed.kind !== "string")) {
|
|
7370
|
+
return failure(
|
|
7371
|
+
parameterFailure(
|
|
7372
|
+
`${path}.kind`,
|
|
7373
|
+
"a kind constraint only on asset-guid parameters",
|
|
7374
|
+
typed.kind,
|
|
7375
|
+
"kind is misplaced"
|
|
7376
|
+
)
|
|
7378
7377
|
);
|
|
7379
7378
|
}
|
|
7380
|
-
|
|
7381
|
-
|
|
7382
|
-
|
|
7383
|
-
|
|
7384
|
-
|
|
7385
|
-
|
|
7379
|
+
for (const field of ["minimum", "maximum"]) {
|
|
7380
|
+
const bound = typed[field];
|
|
7381
|
+
if (bound !== void 0 && (typeof bound !== "number" || !Number.isFinite(bound))) {
|
|
7382
|
+
return failure(
|
|
7383
|
+
parameterFailure(
|
|
7384
|
+
`${path}.${field}`,
|
|
7385
|
+
"a finite numeric bound",
|
|
7386
|
+
bound,
|
|
7387
|
+
"numeric bound is invalid"
|
|
7388
|
+
)
|
|
7389
|
+
);
|
|
7390
|
+
}
|
|
7386
7391
|
}
|
|
7387
|
-
if (!
|
|
7388
|
-
return
|
|
7389
|
-
|
|
7390
|
-
|
|
7391
|
-
|
|
7392
|
-
|
|
7392
|
+
if (!numericType(typed.type) && (typed.minimum !== void 0 || typed.maximum !== void 0)) {
|
|
7393
|
+
return failure(
|
|
7394
|
+
parameterFailure(
|
|
7395
|
+
path,
|
|
7396
|
+
"minimum/maximum only on numeric parameters",
|
|
7397
|
+
typed,
|
|
7398
|
+
"numeric bounds are not meaningful for this parameter type"
|
|
7399
|
+
)
|
|
7393
7400
|
);
|
|
7394
7401
|
}
|
|
7395
|
-
|
|
7396
|
-
|
|
7397
|
-
|
|
7398
|
-
`$.externalAssets[${JSON.stringify(alias)}]`,
|
|
7399
|
-
"a unique foreign GUID not owned by this package",
|
|
7400
|
-
guidValue,
|
|
7401
|
-
sourcePath
|
|
7402
|
+
if (typed.minimum !== void 0 && typed.maximum !== void 0 && typed.minimum > typed.maximum) {
|
|
7403
|
+
return failure(
|
|
7404
|
+
parameterFailure(path, "minimum <= maximum", typed, "numeric bounds are reversed")
|
|
7402
7405
|
);
|
|
7403
7406
|
}
|
|
7404
|
-
|
|
7407
|
+
const defaultResult = normalizeParameterValue(typed, typed.default, `${path}.default`);
|
|
7408
|
+
if (!defaultResult.ok) return defaultResult;
|
|
7409
|
+
normalized.push({
|
|
7410
|
+
...typed,
|
|
7411
|
+
default: defaultResult.value,
|
|
7412
|
+
...typed.values === void 0 ? {} : { values: Object.freeze([...typed.values]) }
|
|
7413
|
+
});
|
|
7405
7414
|
}
|
|
7406
|
-
return ok(
|
|
7415
|
+
return ok(Object.freeze(normalized));
|
|
7407
7416
|
}
|
|
7408
|
-
function
|
|
7409
|
-
|
|
7410
|
-
|
|
7411
|
-
|
|
7412
|
-
|
|
7413
|
-
|
|
7414
|
-
|
|
7415
|
-
|
|
7416
|
-
|
|
7417
|
-
|
|
7418
|
-
|
|
7419
|
-
|
|
7420
|
-
|
|
7421
|
-
|
|
7422
|
-
importer: "pack-ts",
|
|
7423
|
-
source,
|
|
7424
|
-
importSettings: { contractVersion: "1.0.0", externalAssets },
|
|
7425
|
-
subAssets
|
|
7426
|
-
};
|
|
7417
|
+
function definePackageId(value) {
|
|
7418
|
+
if (isPackageId(value)) return value.slice();
|
|
7419
|
+
const parsed = PackageId.parse(value);
|
|
7420
|
+
if (!parsed.ok) {
|
|
7421
|
+
const error = authoringError(
|
|
7422
|
+
"pack-package-id-invalid",
|
|
7423
|
+
"a 36-character RFC 4122 UUID packageId",
|
|
7424
|
+
"use PackageId.random() or repair the packageId literal before loading the Pack",
|
|
7425
|
+
{ value },
|
|
7426
|
+
value
|
|
7427
|
+
);
|
|
7428
|
+
throw Object.assign(new TypeError(error.hint), error);
|
|
7429
|
+
}
|
|
7430
|
+
return parsed.value;
|
|
7427
7431
|
}
|
|
7428
|
-
|
|
7429
|
-
|
|
7430
|
-
|
|
7432
|
+
function cloneDefinition(definition) {
|
|
7433
|
+
const parameters = "parameters" in definition ? Object.freeze(
|
|
7434
|
+
definition.parameters.map(
|
|
7435
|
+
(parameter) => Object.freeze({
|
|
7436
|
+
...parameter,
|
|
7437
|
+
default: cloneValue(parameter.default),
|
|
7438
|
+
...parameter.values === void 0 ? {} : { values: Object.freeze(parameter.values.map((value) => cloneValue(value))) }
|
|
7439
|
+
})
|
|
7440
|
+
)
|
|
7441
|
+
) : void 0;
|
|
7442
|
+
const sceneComponents = definition.sceneComponents === void 0 ? void 0 : Object.freeze(
|
|
7443
|
+
definition.sceneComponents.map(
|
|
7444
|
+
(component) => Object.freeze({
|
|
7445
|
+
name: component.name,
|
|
7446
|
+
fields: Object.freeze({ ...component.fields })
|
|
7447
|
+
})
|
|
7448
|
+
)
|
|
7449
|
+
);
|
|
7450
|
+
return Object.freeze({
|
|
7451
|
+
...definition,
|
|
7452
|
+
packageId: definition.packageId.slice(),
|
|
7453
|
+
...parameters === void 0 ? {} : { parameters },
|
|
7454
|
+
...sceneComponents === void 0 ? {} : { sceneComponents }
|
|
7455
|
+
});
|
|
7456
|
+
}
|
|
7457
|
+
function definePack(definition) {
|
|
7458
|
+
const validated = validatePackDefinition(definition);
|
|
7459
|
+
if (!validated.ok) throw Object.assign(new TypeError(validated.error.hint), validated.error);
|
|
7460
|
+
return cloneDefinition(
|
|
7461
|
+
validated.value
|
|
7462
|
+
);
|
|
7463
|
+
}
|
|
7464
|
+
function projectParameterizedPackMeta(definition, sourcePath) {
|
|
7431
7465
|
return {
|
|
7432
|
-
|
|
7433
|
-
|
|
7434
|
-
|
|
7435
|
-
|
|
7466
|
+
schemaVersion: "2.0.0",
|
|
7467
|
+
kind: "parameterized-pack-source",
|
|
7468
|
+
packageId: PackageId.format(definition.packageId),
|
|
7469
|
+
source: sourcePath,
|
|
7470
|
+
..."parameters" in definition ? {
|
|
7471
|
+
parameters: definition.parameters.map((parameter) => ({
|
|
7472
|
+
name: parameter.name,
|
|
7473
|
+
type: parameter.type,
|
|
7474
|
+
default: jsonParameterValue(parameter.default),
|
|
7475
|
+
...parameter.minimum === void 0 ? {} : { minimum: parameter.minimum },
|
|
7476
|
+
...parameter.maximum === void 0 ? {} : { maximum: parameter.maximum },
|
|
7477
|
+
...parameter.values === void 0 ? {} : { values: parameter.values },
|
|
7478
|
+
...parameter.kind === void 0 ? {} : { kind: parameter.kind }
|
|
7479
|
+
}))
|
|
7480
|
+
} : {}
|
|
7436
7481
|
};
|
|
7437
7482
|
}
|
|
7438
|
-
function
|
|
7439
|
-
return
|
|
7440
|
-
}
|
|
7441
|
-
function catalogRowProjectionFor(subject, execution, lifecycle) {
|
|
7442
|
-
const projection = catalogProjectionFor(subject, execution, lifecycle);
|
|
7443
|
-
return { ...projection, projection };
|
|
7483
|
+
function jsonParameterValue(value) {
|
|
7484
|
+
return value instanceof Uint8Array ? AssetGuid.format(value) : value;
|
|
7444
7485
|
}
|
|
7445
|
-
function
|
|
7446
|
-
if (
|
|
7447
|
-
|
|
7448
|
-
|
|
7449
|
-
|
|
7450
|
-
|
|
7451
|
-
|
|
7452
|
-
|
|
7486
|
+
function validatePackDefinition(value, sourcePath) {
|
|
7487
|
+
if (!isRecord(value))
|
|
7488
|
+
return failure(
|
|
7489
|
+
parameterFailure("$", "a Pack definition object", value, "definition is not an object")
|
|
7490
|
+
);
|
|
7491
|
+
const unknown = Object.keys(value).find(
|
|
7492
|
+
(key) => !["schemaVersion", "packageId", "name", "parameters", "sceneComponents", "build"].includes(
|
|
7493
|
+
key
|
|
7494
|
+
)
|
|
7495
|
+
);
|
|
7496
|
+
if (unknown !== void 0) {
|
|
7497
|
+
return failure(
|
|
7498
|
+
parameterFailure(
|
|
7499
|
+
`$.${unknown}`,
|
|
7500
|
+
"only schemaVersion, packageId, name, parameters, sceneComponents, and build fields",
|
|
7501
|
+
value[unknown],
|
|
7502
|
+
"legacy static output declarations and external asset tables are not part of v2 authoring"
|
|
7503
|
+
)
|
|
7504
|
+
);
|
|
7505
|
+
}
|
|
7506
|
+
if (value.schemaVersion !== "2.0.0") {
|
|
7507
|
+
return failure(
|
|
7508
|
+
parameterFailure(
|
|
7509
|
+
"$.schemaVersion",
|
|
7510
|
+
"the literal '2.0.0'",
|
|
7511
|
+
value.schemaVersion,
|
|
7512
|
+
"authoring source schema is unsupported"
|
|
7513
|
+
)
|
|
7514
|
+
);
|
|
7515
|
+
}
|
|
7516
|
+
if (!isPackageId(value.packageId)) {
|
|
7517
|
+
return failure(
|
|
7518
|
+
authoringError(
|
|
7519
|
+
"pack-package-id-invalid",
|
|
7520
|
+
"a 16-byte PackageId",
|
|
7521
|
+
"use definePackageId() for the stable source identity",
|
|
7522
|
+
{ sourcePath, propertyPath: "$.packageId" },
|
|
7523
|
+
typeof value.packageId === "string" ? value.packageId : void 0
|
|
7524
|
+
)
|
|
7525
|
+
);
|
|
7526
|
+
}
|
|
7527
|
+
if (value.name !== void 0 && typeof value.name !== "string") {
|
|
7528
|
+
return failure(
|
|
7529
|
+
parameterFailure("$.name", "a string when present", value.name, "display name is malformed")
|
|
7530
|
+
);
|
|
7531
|
+
}
|
|
7532
|
+
if (typeof value.build !== "function") {
|
|
7533
|
+
return failure(
|
|
7534
|
+
parameterFailure("$.build", "a build function", value.build, "build is not callable")
|
|
7535
|
+
);
|
|
7536
|
+
}
|
|
7537
|
+
const sceneComponents = validateSceneComponents(value.sceneComponents);
|
|
7538
|
+
if (!sceneComponents.ok) return sceneComponents;
|
|
7539
|
+
const hasParameters = Object.hasOwn(value, "parameters");
|
|
7540
|
+
if (!hasParameters) {
|
|
7541
|
+
return ok(
|
|
7542
|
+
Object.freeze({
|
|
7543
|
+
schemaVersion: "2.0.0",
|
|
7544
|
+
packageId: value.packageId,
|
|
7545
|
+
...value.name === void 0 ? {} : { name: value.name },
|
|
7546
|
+
...sceneComponents.value === void 0 ? {} : { sceneComponents: sceneComponents.value },
|
|
7547
|
+
build: value.build
|
|
7548
|
+
})
|
|
7549
|
+
);
|
|
7550
|
+
}
|
|
7551
|
+
const parameters = validateParameterDefinitions(value.parameters);
|
|
7552
|
+
if (!parameters.ok) return parameters;
|
|
7553
|
+
return ok(
|
|
7554
|
+
Object.freeze({
|
|
7555
|
+
schemaVersion: "2.0.0",
|
|
7556
|
+
packageId: value.packageId,
|
|
7557
|
+
...value.name === void 0 ? {} : { name: value.name },
|
|
7558
|
+
...sceneComponents.value === void 0 ? {} : { sceneComponents: sceneComponents.value },
|
|
7559
|
+
parameters: parameters.value,
|
|
7560
|
+
build: value.build
|
|
7561
|
+
})
|
|
7562
|
+
);
|
|
7563
|
+
}
|
|
7564
|
+
function isParameterizedPack(value) {
|
|
7565
|
+
return isRecord(value) && Array.isArray(value.parameters) && value.parameters.length > 0;
|
|
7566
|
+
}
|
|
7567
|
+
function resolvePackParameterValues(definition, overrides = {}, inheritedValues) {
|
|
7568
|
+
if (!isRecord(overrides)) {
|
|
7569
|
+
return failure(
|
|
7570
|
+
parameterFailure(
|
|
7571
|
+
"$.values",
|
|
7572
|
+
"an object of sparse parameter overrides",
|
|
7573
|
+
overrides,
|
|
7574
|
+
"values is not an object"
|
|
7575
|
+
)
|
|
7576
|
+
);
|
|
7577
|
+
}
|
|
7578
|
+
const descriptors = new Map(
|
|
7579
|
+
definition.parameters.map((parameter) => [parameter.name, parameter])
|
|
7580
|
+
);
|
|
7581
|
+
for (const name of Object.keys(overrides)) {
|
|
7582
|
+
if (!descriptors.has(name)) {
|
|
7583
|
+
return failure(
|
|
7584
|
+
parameterFailure(
|
|
7585
|
+
`$.values.${name}`,
|
|
7586
|
+
"a declared parameter name",
|
|
7587
|
+
name,
|
|
7588
|
+
"instance contains an unknown parameter"
|
|
7589
|
+
)
|
|
7590
|
+
);
|
|
7591
|
+
}
|
|
7592
|
+
}
|
|
7593
|
+
const values = {};
|
|
7594
|
+
for (const parameter of definition.parameters) {
|
|
7595
|
+
const raw = Object.hasOwn(overrides, parameter.name) ? overrides[parameter.name] : inheritedValues?.[parameter.name] ?? parameter.default;
|
|
7596
|
+
const normalized = normalizeParameterValue(parameter, raw, `$.values.${parameter.name}`);
|
|
7597
|
+
if (!normalized.ok) return normalized;
|
|
7598
|
+
values[parameter.name] = normalized.value;
|
|
7599
|
+
}
|
|
7600
|
+
return ok(Object.freeze(values));
|
|
7601
|
+
}
|
|
7602
|
+
function jsonError(propertyPath, expected, actual, reason) {
|
|
7603
|
+
return failure(
|
|
7604
|
+
authoringError(
|
|
7605
|
+
"pack-parameter-invalid",
|
|
7606
|
+
expected,
|
|
7607
|
+
"repair the v3 pack.json authoring data, then rerun scan or rebuild",
|
|
7608
|
+
{
|
|
7609
|
+
propertyPath,
|
|
7610
|
+
reason,
|
|
7611
|
+
actual: typeof actual === "string" ? actual : JSON.stringify(actual)
|
|
7612
|
+
}
|
|
7613
|
+
)
|
|
7614
|
+
);
|
|
7615
|
+
}
|
|
7616
|
+
function parsePackageId(value, propertyPath) {
|
|
7617
|
+
if (typeof value !== "string") {
|
|
7618
|
+
return failure(
|
|
7619
|
+
authoringError(
|
|
7620
|
+
"pack-package-id-invalid",
|
|
7621
|
+
"a UUID string",
|
|
7622
|
+
"repair packageId in the authoring file",
|
|
7623
|
+
{ propertyPath, value }
|
|
7624
|
+
)
|
|
7625
|
+
);
|
|
7626
|
+
}
|
|
7627
|
+
const parsed = PackageId.parse(value);
|
|
7628
|
+
if (!parsed.ok) {
|
|
7629
|
+
return failure(
|
|
7630
|
+
authoringError(
|
|
7631
|
+
"pack-package-id-invalid",
|
|
7632
|
+
"a 36-character RFC 4122 UUID",
|
|
7633
|
+
"repair packageId or use the authoring gateway to mint one",
|
|
7634
|
+
{ propertyPath, value },
|
|
7635
|
+
value
|
|
7636
|
+
)
|
|
7637
|
+
);
|
|
7638
|
+
}
|
|
7639
|
+
return ok(parsed.value);
|
|
7640
|
+
}
|
|
7641
|
+
function parsePackJsonAsset(value, sourceKey2) {
|
|
7642
|
+
if (!isRecord(value))
|
|
7643
|
+
return jsonError(
|
|
7644
|
+
`$.assets.${sourceKey2}`,
|
|
7645
|
+
"an asset entry object",
|
|
7646
|
+
value,
|
|
7647
|
+
"asset entry is not an object"
|
|
7648
|
+
);
|
|
7649
|
+
const allowed = /* @__PURE__ */ new Set(["kind", "payload", "refs", "name", "artifacts"]);
|
|
7650
|
+
const unknown = Object.keys(value).find((key) => !allowed.has(key));
|
|
7651
|
+
if (unknown !== void 0)
|
|
7652
|
+
return jsonError(
|
|
7653
|
+
`$.assets.${sourceKey2}.${unknown}`,
|
|
7654
|
+
"no GUID or extra authoring field",
|
|
7655
|
+
value[unknown],
|
|
7656
|
+
"direct v3 entries derive identity from their object key"
|
|
7657
|
+
);
|
|
7658
|
+
if (typeof value.kind !== "string" || value.kind.length === 0)
|
|
7659
|
+
return jsonError(
|
|
7660
|
+
`$.assets.${sourceKey2}.kind`,
|
|
7661
|
+
"a non-empty asset kind",
|
|
7662
|
+
value.kind,
|
|
7663
|
+
"asset kind is missing"
|
|
7664
|
+
);
|
|
7665
|
+
if (!isRecord(value.payload))
|
|
7666
|
+
return jsonError(
|
|
7667
|
+
`$.assets.${sourceKey2}.payload`,
|
|
7668
|
+
"a JSON object payload",
|
|
7669
|
+
value.payload,
|
|
7670
|
+
"payload must be a plain object"
|
|
7671
|
+
);
|
|
7672
|
+
if (!Array.isArray(value.refs) || value.refs.some((ref) => typeof ref !== "string" || !isValidAssetGuidString(ref))) {
|
|
7673
|
+
return jsonError(
|
|
7674
|
+
`$.assets.${sourceKey2}.refs`,
|
|
7675
|
+
"an array of UUID references",
|
|
7676
|
+
value.refs,
|
|
7677
|
+
"references must already be real AssetGuids"
|
|
7678
|
+
);
|
|
7679
|
+
}
|
|
7680
|
+
if (value.name !== void 0 && (typeof value.name !== "string" || value.name.length === 0))
|
|
7681
|
+
return jsonError(
|
|
7682
|
+
`$.assets.${sourceKey2}.name`,
|
|
7683
|
+
"a non-empty display name when present",
|
|
7684
|
+
value.name,
|
|
7685
|
+
"asset name is malformed"
|
|
7686
|
+
);
|
|
7687
|
+
if (value.artifacts !== void 0 && !isRecord(value.artifacts))
|
|
7688
|
+
return jsonError(
|
|
7689
|
+
`$.assets.${sourceKey2}.artifacts`,
|
|
7690
|
+
"an artifact descriptor object when present",
|
|
7691
|
+
value.artifacts,
|
|
7692
|
+
"artifacts are not an object"
|
|
7693
|
+
);
|
|
7694
|
+
const base = {
|
|
7695
|
+
kind: value.kind,
|
|
7696
|
+
payload: value.payload,
|
|
7697
|
+
refs: Object.freeze([...value.refs]),
|
|
7698
|
+
...value.name === void 0 ? {} : { name: value.name }
|
|
7699
|
+
};
|
|
7700
|
+
if (value.artifacts === void 0) return ok(base);
|
|
7701
|
+
const withArtifacts = {
|
|
7702
|
+
...base,
|
|
7703
|
+
artifacts: value.artifacts
|
|
7704
|
+
};
|
|
7705
|
+
return ok(withArtifacts);
|
|
7706
|
+
}
|
|
7707
|
+
function parseParameterizedPackJson(value) {
|
|
7708
|
+
if (!isRecord(value))
|
|
7709
|
+
return jsonError("$", "a v3 pack.json object", value, "document is not an object");
|
|
7710
|
+
if (value.schemaVersion !== "3.0.0")
|
|
7711
|
+
return jsonError(
|
|
7712
|
+
"$.schemaVersion",
|
|
7713
|
+
"the literal '3.0.0'",
|
|
7714
|
+
value.schemaVersion,
|
|
7715
|
+
"document schema is not v3"
|
|
7716
|
+
);
|
|
7717
|
+
const unknown = Object.keys(value).find(
|
|
7718
|
+
(key) => !["schemaVersion", "packageId", "assets", "parent", "values"].includes(key)
|
|
7719
|
+
);
|
|
7720
|
+
if (unknown !== void 0)
|
|
7721
|
+
return jsonError(
|
|
7722
|
+
`$.${unknown}`,
|
|
7723
|
+
"no extra top-level authoring fields",
|
|
7724
|
+
value[unknown],
|
|
7725
|
+
"keep the v3 document to packageId+assets or packageId+parent+values"
|
|
7726
|
+
);
|
|
7727
|
+
const packageResult = parsePackageId(value.packageId, "$.packageId");
|
|
7728
|
+
if (!packageResult.ok) return packageResult;
|
|
7729
|
+
const hasAssets = Object.hasOwn(value, "assets");
|
|
7730
|
+
const hasParent = Object.hasOwn(value, "parent");
|
|
7731
|
+
const hasValues = Object.hasOwn(value, "values");
|
|
7732
|
+
if (hasAssets && (hasParent || hasValues))
|
|
7733
|
+
return jsonError(
|
|
7734
|
+
"$",
|
|
7735
|
+
"assets or parent+values, never both",
|
|
7736
|
+
value,
|
|
7737
|
+
"direct and instance branches are mutually exclusive"
|
|
7738
|
+
);
|
|
7739
|
+
if (hasAssets) {
|
|
7740
|
+
if (!isRecord(value.assets))
|
|
7741
|
+
return jsonError(
|
|
7742
|
+
"$.assets",
|
|
7743
|
+
"a sourceKey to asset object",
|
|
7744
|
+
value.assets,
|
|
7745
|
+
"direct assets are not an object"
|
|
7746
|
+
);
|
|
7747
|
+
const assets = {};
|
|
7748
|
+
for (const [sourceKey2, entry] of Object.entries(value.assets)) {
|
|
7749
|
+
if (!isValidPackSourceKey(sourceKey2))
|
|
7750
|
+
return failure(sourceKeyFailure(sourceKey2, `$.assets.${sourceKey2}`));
|
|
7751
|
+
const parsed = parsePackJsonAsset(entry, sourceKey2);
|
|
7752
|
+
if (!parsed.ok) return parsed;
|
|
7753
|
+
assets[sourceKey2] = parsed.value;
|
|
7754
|
+
}
|
|
7755
|
+
return ok({
|
|
7756
|
+
format: "direct",
|
|
7757
|
+
schemaVersion: "3.0.0",
|
|
7758
|
+
packageId: packageResult.value,
|
|
7759
|
+
assets: Object.freeze(assets)
|
|
7760
|
+
});
|
|
7761
|
+
}
|
|
7762
|
+
if (!hasParent || !hasValues || hasAssets)
|
|
7763
|
+
return jsonError(
|
|
7764
|
+
"$",
|
|
7765
|
+
"parent and values for an instance document",
|
|
7766
|
+
value,
|
|
7767
|
+
"instance branch is incomplete"
|
|
7768
|
+
);
|
|
7769
|
+
const parentResult = parsePackageId(value.parent, "$.parent");
|
|
7770
|
+
if (!parentResult.ok) return parentResult;
|
|
7771
|
+
if (!isRecord(value.values))
|
|
7772
|
+
return jsonError(
|
|
7773
|
+
"$.values",
|
|
7774
|
+
"a sparse parameter object",
|
|
7775
|
+
value.values,
|
|
7776
|
+
"instance values are not an object"
|
|
7777
|
+
);
|
|
7778
|
+
return ok({
|
|
7779
|
+
format: "instance",
|
|
7780
|
+
schemaVersion: "3.0.0",
|
|
7781
|
+
packageId: packageResult.value,
|
|
7782
|
+
parent: parentResult.value,
|
|
7783
|
+
values: Object.freeze({ ...value.values })
|
|
7784
|
+
});
|
|
7785
|
+
}
|
|
7786
|
+
var parsePackJson = parseParameterizedPackJson;
|
|
7787
|
+
var parsePackAuthoringJson = parseParameterizedPackJson;
|
|
7788
|
+
function projectDirectPackJson(value) {
|
|
7789
|
+
const parsed = "format" in value ? ok(value) : parseParameterizedPackJson(value);
|
|
7790
|
+
if (!parsed.ok) return parsed;
|
|
7791
|
+
if (parsed.value.format !== "direct") {
|
|
7792
|
+
return failure(
|
|
7793
|
+
authoringError(
|
|
7794
|
+
"pack-parameter-invalid",
|
|
7795
|
+
"a direct v3 pack.json",
|
|
7796
|
+
"projectDirectPackJson accepts the direct branch only",
|
|
7797
|
+
{ observed: parsed.value.format }
|
|
7798
|
+
)
|
|
7799
|
+
);
|
|
7800
|
+
}
|
|
7801
|
+
const assets = [];
|
|
7802
|
+
for (const [sourceKey2, entry] of Object.entries(parsed.value.assets).sort(
|
|
7803
|
+
([left], [right]) => left.localeCompare(right)
|
|
7804
|
+
)) {
|
|
7805
|
+
assets.push({
|
|
7806
|
+
...entry,
|
|
7807
|
+
guid: AssetGuid.format(AssetGuid.derive(parsed.value.packageId, sourceKey2)),
|
|
7808
|
+
sourceKey: sourceKey2
|
|
7809
|
+
});
|
|
7810
|
+
}
|
|
7811
|
+
return ok({ packageId: PackageId.format(parsed.value.packageId), assets: Object.freeze(assets) });
|
|
7812
|
+
}
|
|
7813
|
+
function subjectId(subject) {
|
|
7814
|
+
return PackageId.format(subject.packageId).toLowerCase();
|
|
7815
|
+
}
|
|
7816
|
+
async function resolvePackParameterInheritance(subject, readParent) {
|
|
7817
|
+
const visited = /* @__PURE__ */ new Set();
|
|
7818
|
+
async function visit(current, path) {
|
|
7819
|
+
const currentId = subjectId(current);
|
|
7820
|
+
if (visited.has(currentId) || path.includes(currentId)) {
|
|
7821
|
+
return failure(
|
|
7822
|
+
authoringError(
|
|
7823
|
+
"pack-parent-cycle",
|
|
7824
|
+
"a finite acyclic Pack parent chain",
|
|
7825
|
+
"inspect parentChain and repair the first repeated packageId",
|
|
7826
|
+
{ packageId: currentId, parentChain: [...path, currentId] }
|
|
7827
|
+
)
|
|
7828
|
+
);
|
|
7829
|
+
}
|
|
7830
|
+
visited.add(currentId);
|
|
7831
|
+
const nextPath = [...path, currentId];
|
|
7832
|
+
if (current.format === "direct") {
|
|
7833
|
+
return failure(
|
|
7834
|
+
authoringError(
|
|
7835
|
+
"pack-parent-not-parameterized",
|
|
7836
|
+
"a parameterized Pack source as the parent",
|
|
7837
|
+
"direct packs cannot be instance parents; point the instance at a parameterized source",
|
|
7838
|
+
{ packageId: currentId }
|
|
7839
|
+
)
|
|
7840
|
+
);
|
|
7841
|
+
}
|
|
7842
|
+
if (current.format === "source") {
|
|
7843
|
+
const descriptors2 = validateParameterDefinitions(current.parameters, "$.parameters");
|
|
7844
|
+
if (!descriptors2.ok) return descriptors2;
|
|
7845
|
+
if (descriptors2.value.length === 0) {
|
|
7846
|
+
return failure(
|
|
7847
|
+
authoringError(
|
|
7848
|
+
"pack-parent-not-parameterized",
|
|
7849
|
+
"the parent source to declare a non-empty parameter list",
|
|
7850
|
+
"use clone for an independent zero-parameter Pack instead of creating an empty instance",
|
|
7851
|
+
{ packageId: currentId }
|
|
7852
|
+
)
|
|
7853
|
+
);
|
|
7854
|
+
}
|
|
7855
|
+
const definition2 = {
|
|
7856
|
+
packageId: current.packageId,
|
|
7857
|
+
parameters: descriptors2.value};
|
|
7858
|
+
const values2 = resolvePackParameterValues(definition2);
|
|
7859
|
+
if (!values2.ok) return values2;
|
|
7860
|
+
return ok({
|
|
7861
|
+
packageId: current.packageId,
|
|
7862
|
+
rootPackageId: current.packageId,
|
|
7863
|
+
values: values2.value,
|
|
7864
|
+
parentChain: [],
|
|
7865
|
+
parameters: descriptors2.value
|
|
7866
|
+
});
|
|
7867
|
+
}
|
|
7868
|
+
const parent = await readParent(current.parent);
|
|
7869
|
+
if (parent === void 0) {
|
|
7870
|
+
return failure(
|
|
7871
|
+
authoringError(
|
|
7872
|
+
"pack-parent-not-found",
|
|
7873
|
+
"the parent packageId to resolve in the source index",
|
|
7874
|
+
"inspect the parent locator or recreate the instance from a live parameterized Pack",
|
|
7875
|
+
{ packageId: currentId, parent: PackageId.format(current.parent) }
|
|
7876
|
+
)
|
|
7877
|
+
);
|
|
7878
|
+
}
|
|
7879
|
+
if (PackageId.format(parent.packageId).toLowerCase() !== PackageId.format(current.parent).toLowerCase()) {
|
|
7880
|
+
return failure(
|
|
7881
|
+
authoringError(
|
|
7882
|
+
"pack-parent-not-found",
|
|
7883
|
+
"the parent reader to return the requested packageId",
|
|
7884
|
+
"repair the Source Index locator and retry inheritance resolution",
|
|
7885
|
+
{
|
|
7886
|
+
packageId: currentId,
|
|
7887
|
+
requestedParent: PackageId.format(current.parent),
|
|
7888
|
+
observedParent: PackageId.format(parent.packageId)
|
|
7889
|
+
}
|
|
7890
|
+
)
|
|
7891
|
+
);
|
|
7892
|
+
}
|
|
7893
|
+
const resolvedParent = await visit(parent, nextPath);
|
|
7894
|
+
if (!resolvedParent.ok) return resolvedParent;
|
|
7895
|
+
const descriptors = resolvedParent.value.parameters;
|
|
7896
|
+
const definition = {
|
|
7897
|
+
packageId: resolvedParent.value.rootPackageId,
|
|
7898
|
+
parameters: descriptors};
|
|
7899
|
+
const values = resolvePackParameterValues(
|
|
7900
|
+
definition,
|
|
7901
|
+
current.values,
|
|
7902
|
+
resolvedParent.value.values
|
|
7903
|
+
);
|
|
7904
|
+
if (!values.ok) return values;
|
|
7905
|
+
return ok({
|
|
7906
|
+
packageId: current.packageId,
|
|
7907
|
+
rootPackageId: resolvedParent.value.rootPackageId,
|
|
7908
|
+
values: values.value,
|
|
7909
|
+
parentChain: [PackageId.format(current.parent), ...resolvedParent.value.parentChain],
|
|
7910
|
+
parameters: descriptors
|
|
7911
|
+
});
|
|
7912
|
+
}
|
|
7913
|
+
return visit(subject, []);
|
|
7914
|
+
}
|
|
7915
|
+
var resolvePackInheritance = resolvePackParameterInheritance;
|
|
7916
|
+
var PARAMETERIZED_PACK_OPERATION_IDS = [
|
|
7917
|
+
"asset.list",
|
|
7918
|
+
"asset.inspect",
|
|
7919
|
+
"asset.resolve",
|
|
7920
|
+
"asset.verify",
|
|
7921
|
+
"asset-source.create",
|
|
7922
|
+
"asset-source.clone",
|
|
7923
|
+
"asset-source.create-instance",
|
|
7924
|
+
"asset-source.apply-values",
|
|
7925
|
+
"asset-source.rebuild",
|
|
7926
|
+
"asset-source.cold-cook"
|
|
7927
|
+
];
|
|
7928
|
+
function createParameterizedPackAuthoringGateway(port) {
|
|
7929
|
+
const requests = /* @__PURE__ */ new Map();
|
|
7930
|
+
return {
|
|
7931
|
+
execute(operation) {
|
|
7932
|
+
if (typeof operation.requestId !== "string" || operation.requestId.trim().length === 0) {
|
|
7933
|
+
return Promise.resolve(
|
|
7934
|
+
failure(
|
|
7935
|
+
authoringError(
|
|
7936
|
+
"pack-source-revision-conflict",
|
|
7937
|
+
"a non-empty caller-minted requestId",
|
|
7938
|
+
"mint a new requestId and retry",
|
|
7939
|
+
{ requestId: operation.requestId }
|
|
7940
|
+
)
|
|
7941
|
+
)
|
|
7942
|
+
);
|
|
7943
|
+
}
|
|
7944
|
+
let fingerprint;
|
|
7945
|
+
try {
|
|
7946
|
+
fingerprint = JSON.stringify(operation);
|
|
7947
|
+
} catch (cause) {
|
|
7948
|
+
return Promise.resolve(
|
|
7949
|
+
failure(
|
|
7950
|
+
authoringError(
|
|
7951
|
+
"pack-parameter-invalid",
|
|
7952
|
+
"a JSON-serialisable authoring operation",
|
|
7953
|
+
"remove non-serialisable operation fields and retry with a new requestId",
|
|
7954
|
+
{
|
|
7955
|
+
requestId: operation.requestId,
|
|
7956
|
+
cause: cause instanceof Error ? cause.message : String(cause)
|
|
7957
|
+
}
|
|
7958
|
+
)
|
|
7959
|
+
)
|
|
7960
|
+
);
|
|
7961
|
+
}
|
|
7962
|
+
const previous = requests.get(operation.requestId);
|
|
7963
|
+
if (previous !== void 0) {
|
|
7964
|
+
if (previous.fingerprint === fingerprint) return previous.result;
|
|
7965
|
+
return Promise.resolve(
|
|
7966
|
+
failure(
|
|
7967
|
+
authoringError(
|
|
7968
|
+
"pack-source-revision-conflict",
|
|
7969
|
+
"one immutable operation per requestId",
|
|
7970
|
+
"read the original result or mint a new requestId",
|
|
7971
|
+
{ requestId: operation.requestId }
|
|
7972
|
+
)
|
|
7973
|
+
)
|
|
7974
|
+
);
|
|
7975
|
+
}
|
|
7976
|
+
const result = Promise.resolve().then(() => port.execute(operation)).catch(
|
|
7977
|
+
(cause) => failure(
|
|
7978
|
+
authoringError(
|
|
7979
|
+
"pack-parameter-invalid",
|
|
7980
|
+
"the Pack authoring port to return a structured Result",
|
|
7981
|
+
"repair the gateway port failure, then retry with a new requestId",
|
|
7982
|
+
{
|
|
7983
|
+
requestId: operation.requestId,
|
|
7984
|
+
cause: cause instanceof Error ? cause.message : String(cause)
|
|
7985
|
+
}
|
|
7986
|
+
)
|
|
7987
|
+
)
|
|
7988
|
+
);
|
|
7989
|
+
requests.set(operation.requestId, { fingerprint, result });
|
|
7990
|
+
return result;
|
|
7991
|
+
}
|
|
7992
|
+
};
|
|
7993
|
+
}
|
|
7994
|
+
var PARAMETERIZED_PACK_OPERATION_DESCRIPTORS = PARAMETERIZED_PACK_OPERATION_IDS.map(
|
|
7995
|
+
(id) => ({
|
|
7996
|
+
id,
|
|
7997
|
+
domain: id.startsWith("asset-source.") ? "session" : "asset",
|
|
7998
|
+
readOnly: id.startsWith("asset."),
|
|
7999
|
+
requiresRevision: !id.startsWith("asset.") && id !== "asset-source.create"
|
|
8000
|
+
})
|
|
8001
|
+
);
|
|
8002
|
+
|
|
8003
|
+
// src/scriptable-pack.ts
|
|
8004
|
+
var SCRIPTABLE_PACK_ASSET_KINDS = [
|
|
8005
|
+
"mesh",
|
|
8006
|
+
"material",
|
|
8007
|
+
"scene",
|
|
8008
|
+
"texture",
|
|
8009
|
+
"equirect",
|
|
8010
|
+
"sampler",
|
|
8011
|
+
"font",
|
|
8012
|
+
"render-pipeline",
|
|
8013
|
+
"tileset",
|
|
8014
|
+
"video",
|
|
8015
|
+
"skeleton",
|
|
8016
|
+
"skin",
|
|
8017
|
+
"animation-clip",
|
|
8018
|
+
"animation-graph",
|
|
8019
|
+
"audio",
|
|
8020
|
+
"particle-effect",
|
|
8021
|
+
"ies-profile"
|
|
8022
|
+
];
|
|
8023
|
+
function isScriptablePackAssetKind(value) {
|
|
8024
|
+
return SCRIPTABLE_PACK_ASSET_KINDS.includes(value);
|
|
8025
|
+
}
|
|
8026
|
+
function sceneComponentFieldType(value) {
|
|
8027
|
+
if (typeof value === "string") return value;
|
|
8028
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
8029
|
+
const type = value.type;
|
|
8030
|
+
return typeof type === "string" ? type : void 0;
|
|
8031
|
+
}
|
|
8032
|
+
function projectScriptablePackSceneComponents(components) {
|
|
8033
|
+
return (components ?? []).map((component) => ({
|
|
8034
|
+
name: component.name,
|
|
8035
|
+
fields: Object.fromEntries(
|
|
8036
|
+
Object.entries(component.fields).map(([fieldName, field]) => [
|
|
8037
|
+
fieldName,
|
|
8038
|
+
sceneComponentFieldType(field)
|
|
8039
|
+
])
|
|
8040
|
+
)
|
|
8041
|
+
}));
|
|
8042
|
+
}
|
|
8043
|
+
|
|
8044
|
+
// src/catalog-projection.ts
|
|
8045
|
+
function catalogProjectionFor(subject, execution, lifecycle) {
|
|
8046
|
+
return {
|
|
8047
|
+
subject,
|
|
8048
|
+
execution,
|
|
8049
|
+
lifecycle,
|
|
8050
|
+
operations: catalogOperationsFor({ subject, execution, lifecycle })
|
|
8051
|
+
};
|
|
8052
|
+
}
|
|
8053
|
+
function currentProjectionFor(subject, execution) {
|
|
8054
|
+
return catalogRowProjectionFor(subject, execution, "current");
|
|
8055
|
+
}
|
|
8056
|
+
function catalogRowProjectionFor(subject, execution, lifecycle) {
|
|
8057
|
+
const projection = catalogProjectionFor(subject, execution, lifecycle);
|
|
8058
|
+
return { ...projection, projection };
|
|
8059
|
+
}
|
|
8060
|
+
function referenceRelations(guid, refs, provenance) {
|
|
8061
|
+
if (refs === void 0 || refs.length === 0) return void 0;
|
|
8062
|
+
return refs.map((ref) => ({
|
|
8063
|
+
from: { type: "asset", id: guid },
|
|
8064
|
+
to: { type: "asset", id: ref },
|
|
8065
|
+
type: "references",
|
|
8066
|
+
policy: { strength: "required" },
|
|
8067
|
+
provenance
|
|
7453
8068
|
}));
|
|
7454
8069
|
}
|
|
7455
8070
|
function producerFields(producer, output) {
|
|
@@ -7531,10 +8146,10 @@ function projectCookedPackageEntry(entry, projection) {
|
|
|
7531
8146
|
refs: projection.refs
|
|
7532
8147
|
};
|
|
7533
8148
|
}
|
|
7534
|
-
function runtimeCatalogRowError(
|
|
8149
|
+
function runtimeCatalogRowError(subjectId2, expected) {
|
|
7535
8150
|
const diagnostic = {
|
|
7536
8151
|
code: "invalid-producer-fact",
|
|
7537
|
-
subject: { type: "asset", id:
|
|
8152
|
+
subject: { type: "asset", id: subjectId2 },
|
|
7538
8153
|
expected,
|
|
7539
8154
|
hint: "recook the source and publish one current runtime Catalog row",
|
|
7540
8155
|
authority: "producer"
|
|
@@ -7585,27 +8200,6 @@ function projectRuntimeCatalogRow(input) {
|
|
|
7585
8200
|
}
|
|
7586
8201
|
return projectRuntimeCatalogRowValue(input);
|
|
7587
8202
|
}
|
|
7588
|
-
function loadAssetConfig(cwd) {
|
|
7589
|
-
let pkg;
|
|
7590
|
-
try {
|
|
7591
|
-
pkg = JSON.parse(readFileSync(join(cwd, "package.json"), "utf-8"));
|
|
7592
|
-
} catch {
|
|
7593
|
-
return { roots: [join(cwd, "assets")], paths: {} };
|
|
7594
|
-
}
|
|
7595
|
-
const assets = pkg.forgeax?.assets;
|
|
7596
|
-
const rawRoots = assets?.roots;
|
|
7597
|
-
const roots = Array.isArray(rawRoots) && rawRoots.length > 0 ? rawRoots.map((r) => join(cwd, r)) : [join(cwd, "assets")];
|
|
7598
|
-
const rawPaths = assets?.paths;
|
|
7599
|
-
const paths = {};
|
|
7600
|
-
if (rawPaths !== void 0 && rawPaths !== null && typeof rawPaths === "object") {
|
|
7601
|
-
for (const [name, dir] of Object.entries(rawPaths)) {
|
|
7602
|
-
if (typeof dir === "string") {
|
|
7603
|
-
paths[name] = join(cwd, dir);
|
|
7604
|
-
}
|
|
7605
|
-
}
|
|
7606
|
-
}
|
|
7607
|
-
return { roots, paths };
|
|
7608
|
-
}
|
|
7609
8203
|
|
|
7610
8204
|
// src/deriveAssetName.ts
|
|
7611
8205
|
function baseName(p) {
|
|
@@ -7613,85 +8207,26 @@ function baseName(p) {
|
|
|
7613
8207
|
const idx = Math.max(trimmed.lastIndexOf("/"), trimmed.lastIndexOf("\\"));
|
|
7614
8208
|
return idx === -1 ? trimmed : trimmed.slice(idx + 1);
|
|
7615
8209
|
}
|
|
7616
|
-
function deriveAssetName(packagePath,
|
|
7617
|
-
if (packagePath === null) {
|
|
7618
|
-
return storedName ?? "";
|
|
7619
|
-
}
|
|
7620
|
-
if (assetCount === 1) {
|
|
7621
|
-
return baseName(packagePath);
|
|
7622
|
-
}
|
|
8210
|
+
function deriveAssetName(packagePath, _assetCount, storedName) {
|
|
7623
8211
|
if (storedName !== void 0) {
|
|
7624
8212
|
return storedName;
|
|
7625
8213
|
}
|
|
8214
|
+
if (packagePath === null) {
|
|
8215
|
+
return "";
|
|
8216
|
+
}
|
|
7626
8217
|
return baseName(packagePath);
|
|
7627
8218
|
}
|
|
7628
8219
|
function deriveSourceName(metaFileName) {
|
|
7629
8220
|
return metaFileName.replace(/\.meta\.json$/, "");
|
|
7630
8221
|
}
|
|
7631
|
-
|
|
7632
|
-
function isPathEscape(pathDir, resolved) {
|
|
7633
|
-
const rel = posix.relative(pathDir, resolved);
|
|
7634
|
-
return rel.startsWith("..") || posix.isAbsolute(rel);
|
|
7635
|
-
}
|
|
7636
|
-
function resolveAssetSource(metaPath, source, paths) {
|
|
8222
|
+
function resolveAssetSource(metaPath, source) {
|
|
7637
8223
|
if (source === void 0) {
|
|
7638
8224
|
const metaDir = dirname(metaPath);
|
|
7639
|
-
const metaName = deriveAssetName(metaPath
|
|
8225
|
+
const metaName = deriveAssetName(metaPath);
|
|
7640
8226
|
const derived = deriveSourceName(metaName);
|
|
7641
|
-
return
|
|
7642
|
-
}
|
|
7643
|
-
if (source.startsWith("@")) {
|
|
7644
|
-
const match = source.match(PATH_REF_RE);
|
|
7645
|
-
if (!match) {
|
|
7646
|
-
return err(
|
|
7647
|
-
new PackError({
|
|
7648
|
-
code: "pack-malformed-path-ref",
|
|
7649
|
-
expected: "source in format @<name>/<rest>",
|
|
7650
|
-
hint: PACK_ERROR_HINTS["pack-malformed-path-ref"],
|
|
7651
|
-
detail: {
|
|
7652
|
-
code: "pack-malformed-path-ref",
|
|
7653
|
-
reason: "format",
|
|
7654
|
-
rawSource: source,
|
|
7655
|
-
expectedFormat: "@<name>/<rest>"
|
|
7656
|
-
}
|
|
7657
|
-
})
|
|
7658
|
-
);
|
|
7659
|
-
}
|
|
7660
|
-
const [, name, rest] = match;
|
|
7661
|
-
const pathDir = paths[name];
|
|
7662
|
-
if (pathDir === void 0) {
|
|
7663
|
-
return err(
|
|
7664
|
-
new PackError({
|
|
7665
|
-
code: "pack-unknown-path",
|
|
7666
|
-
expected: "path name found in package.json#forgeax.assets.paths",
|
|
7667
|
-
hint: PACK_ERROR_HINTS["pack-unknown-path"],
|
|
7668
|
-
detail: {
|
|
7669
|
-
code: "pack-unknown-path",
|
|
7670
|
-
pathName: name,
|
|
7671
|
-
knownNames: Object.keys(paths)
|
|
7672
|
-
}
|
|
7673
|
-
})
|
|
7674
|
-
);
|
|
7675
|
-
}
|
|
7676
|
-
const resolved = resolve(pathDir, rest);
|
|
7677
|
-
if (isPathEscape(pathDir, resolved)) {
|
|
7678
|
-
return err(
|
|
7679
|
-
new PackError({
|
|
7680
|
-
code: "pack-malformed-path-ref",
|
|
7681
|
-
expected: "rest path must not escape the declared path directory",
|
|
7682
|
-
hint: PACK_ERROR_HINTS["pack-malformed-path-ref"],
|
|
7683
|
-
detail: {
|
|
7684
|
-
code: "pack-malformed-path-ref",
|
|
7685
|
-
reason: "escape",
|
|
7686
|
-
rawSource: source,
|
|
7687
|
-
expectedFormat: "@<name>/<rest>"
|
|
7688
|
-
}
|
|
7689
|
-
})
|
|
7690
|
-
);
|
|
7691
|
-
}
|
|
7692
|
-
return ok(resolved);
|
|
8227
|
+
return resolve(metaDir, derived);
|
|
7693
8228
|
}
|
|
7694
|
-
return
|
|
8229
|
+
return resolve(dirname(metaPath), source);
|
|
7695
8230
|
}
|
|
7696
8231
|
function isRecord2(value) {
|
|
7697
8232
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -7699,25 +8234,25 @@ function isRecord2(value) {
|
|
|
7699
8234
|
function hasText(value) {
|
|
7700
8235
|
return typeof value === "string" && value.length > 0;
|
|
7701
8236
|
}
|
|
7702
|
-
function issue(code,
|
|
7703
|
-
const subject = { type: "asset", id:
|
|
8237
|
+
function issue(code, subjectId2, expected, hint, actual, authority = "producer") {
|
|
8238
|
+
const subject = { type: "asset", id: subjectId2 };
|
|
7704
8239
|
return {
|
|
7705
8240
|
ok: false,
|
|
7706
8241
|
error: {
|
|
7707
8242
|
code,
|
|
7708
8243
|
subject,
|
|
7709
8244
|
expected,
|
|
7710
|
-
...
|
|
8245
|
+
...actual === void 0 ? {} : { actual },
|
|
7711
8246
|
hint,
|
|
7712
8247
|
authority
|
|
7713
8248
|
}
|
|
7714
8249
|
};
|
|
7715
8250
|
}
|
|
7716
|
-
function validateFacts(value,
|
|
8251
|
+
function validateFacts(value, subjectId2) {
|
|
7717
8252
|
if ("packageId" in value && !hasText(value.packageId)) {
|
|
7718
8253
|
return issue(
|
|
7719
8254
|
"invalid-producer-fact",
|
|
7720
|
-
|
|
8255
|
+
subjectId2,
|
|
7721
8256
|
"packageId must be a non-empty string",
|
|
7722
8257
|
"publish a stable package identity"
|
|
7723
8258
|
);
|
|
@@ -7727,7 +8262,7 @@ function validateFacts(value, subjectId) {
|
|
|
7727
8262
|
if (!isRecord2(provenance) || !hasText(provenance.provider) || !hasText(provenance.version)) {
|
|
7728
8263
|
return issue(
|
|
7729
8264
|
"invalid-producer-fact",
|
|
7730
|
-
|
|
8265
|
+
subjectId2,
|
|
7731
8266
|
"provenance.provider and provenance.version must be non-empty",
|
|
7732
8267
|
"publish provider identity and version"
|
|
7733
8268
|
);
|
|
@@ -7738,7 +8273,7 @@ function validateFacts(value, subjectId) {
|
|
|
7738
8273
|
if (!isRecord2(revision) || !hasText(revision.digest) || !hasText(revision.rootId) || typeof revision.observedAt !== "number" || !Number.isFinite(revision.observedAt)) {
|
|
7739
8274
|
return issue(
|
|
7740
8275
|
"invalid-producer-fact",
|
|
7741
|
-
|
|
8276
|
+
subjectId2,
|
|
7742
8277
|
"revision.digest, revision.rootId and finite revision.observedAt",
|
|
7743
8278
|
"publish a complete resource revision"
|
|
7744
8279
|
);
|
|
@@ -7748,7 +8283,7 @@ function validateFacts(value, subjectId) {
|
|
|
7748
8283
|
if (!Array.isArray(value.diagnostics)) {
|
|
7749
8284
|
return issue(
|
|
7750
8285
|
"invalid-producer-fact",
|
|
7751
|
-
|
|
8286
|
+
subjectId2,
|
|
7752
8287
|
"diagnostics must be an array",
|
|
7753
8288
|
"publish structured diagnostics as an array"
|
|
7754
8289
|
);
|
|
@@ -7757,7 +8292,7 @@ function validateFacts(value, subjectId) {
|
|
|
7757
8292
|
if (!isRecord2(diagnostic) || !hasText(diagnostic.code)) {
|
|
7758
8293
|
return issue(
|
|
7759
8294
|
"invalid-producer-fact",
|
|
7760
|
-
|
|
8295
|
+
subjectId2,
|
|
7761
8296
|
"each diagnostic needs a stable code",
|
|
7762
8297
|
"publish a machine-readable diagnostic code"
|
|
7763
8298
|
);
|
|
@@ -7766,7 +8301,7 @@ function validateFacts(value, subjectId) {
|
|
|
7766
8301
|
if (!isRecord2(diagnostic.subject) || !hasText(diagnostic.subject.id)) {
|
|
7767
8302
|
return issue(
|
|
7768
8303
|
"invalid-producer-fact",
|
|
7769
|
-
|
|
8304
|
+
subjectId2,
|
|
7770
8305
|
"blocking diagnostic.subject must identify an object",
|
|
7771
8306
|
"set subject.type and subject.id"
|
|
7772
8307
|
);
|
|
@@ -7774,7 +8309,7 @@ function validateFacts(value, subjectId) {
|
|
|
7774
8309
|
if (!hasText(diagnostic.expected) || !hasText(diagnostic.hint)) {
|
|
7775
8310
|
return issue(
|
|
7776
8311
|
"invalid-producer-fact",
|
|
7777
|
-
|
|
8312
|
+
subjectId2,
|
|
7778
8313
|
"blocking diagnostics need expected and hint",
|
|
7779
8314
|
"provide an executable recovery hint"
|
|
7780
8315
|
);
|
|
@@ -7784,7 +8319,7 @@ function validateFacts(value, subjectId) {
|
|
|
7784
8319
|
}
|
|
7785
8320
|
return { ok: true, value };
|
|
7786
8321
|
}
|
|
7787
|
-
function validateMetaSourceOverrides(value,
|
|
8322
|
+
function validateMetaSourceOverrides(value, subjectId2) {
|
|
7788
8323
|
if (!("sourceOverrides" in value)) return { ok: true, value };
|
|
7789
8324
|
const declaredSourceKeys = Array.isArray(value.subAssets) ? value.subAssets.flatMap(
|
|
7790
8325
|
(subAsset) => isRecord2(subAsset) && hasText(subAsset.sourceKey) ? [subAsset.sourceKey] : []
|
|
@@ -7793,7 +8328,7 @@ function validateMetaSourceOverrides(value, subjectId) {
|
|
|
7793
8328
|
if (!result.ok) {
|
|
7794
8329
|
return issue(
|
|
7795
8330
|
result.error.code,
|
|
7796
|
-
|
|
8331
|
+
subjectId2,
|
|
7797
8332
|
result.error.expected,
|
|
7798
8333
|
result.error.hint,
|
|
7799
8334
|
result.error.actual,
|
|
@@ -7814,15 +8349,15 @@ function validateProducerContract(value) {
|
|
|
7814
8349
|
"publish a JSON object"
|
|
7815
8350
|
);
|
|
7816
8351
|
}
|
|
7817
|
-
const
|
|
7818
|
-
const facts = validateFacts(value,
|
|
8352
|
+
const subjectId2 = hasText(value.guid) ? value.guid : hasText(value.packageId) ? value.packageId : "unknown";
|
|
8353
|
+
const facts = validateFacts(value, subjectId2);
|
|
7819
8354
|
if (!facts.ok) return facts;
|
|
7820
|
-
const metaOverrides = validateMetaSourceOverrides(value,
|
|
8355
|
+
const metaOverrides = validateMetaSourceOverrides(value, subjectId2);
|
|
7821
8356
|
if (!metaOverrides.ok) return metaOverrides;
|
|
7822
8357
|
if ("kind" in value && !hasText(value.kind)) {
|
|
7823
8358
|
return issue(
|
|
7824
8359
|
"invalid-producer-fact",
|
|
7825
|
-
|
|
8360
|
+
subjectId2,
|
|
7826
8361
|
"kind must be a non-empty open string",
|
|
7827
8362
|
"publish the provider-owned asset kind"
|
|
7828
8363
|
);
|
|
@@ -7830,7 +8365,7 @@ function validateProducerContract(value) {
|
|
|
7830
8365
|
if ("execution" in value && value.execution !== "direct" && value.execution !== "cooked") {
|
|
7831
8366
|
return issue(
|
|
7832
8367
|
"invalid-producer-fact",
|
|
7833
|
-
|
|
8368
|
+
subjectId2,
|
|
7834
8369
|
"execution must be either direct or cooked",
|
|
7835
8370
|
"publish the explicit authoring execution mode"
|
|
7836
8371
|
);
|
|
@@ -7840,7 +8375,7 @@ function validateProducerContract(value) {
|
|
|
7840
8375
|
if (value.sourceKey !== void 0 && !hasText(value.sourceKey)) {
|
|
7841
8376
|
return issue(
|
|
7842
8377
|
"invalid-source-key",
|
|
7843
|
-
|
|
8378
|
+
subjectId2,
|
|
7844
8379
|
"sourceKey must be a non-empty producer-owned string",
|
|
7845
8380
|
"publish a stable semantic sourceKey"
|
|
7846
8381
|
);
|
|
@@ -7848,7 +8383,7 @@ function validateProducerContract(value) {
|
|
|
7848
8383
|
if (value.sourceIndex !== void 0 && (typeof value.sourceIndex !== "number" || !Number.isInteger(value.sourceIndex) || value.sourceIndex < 0)) {
|
|
7849
8384
|
return issue(
|
|
7850
8385
|
"invalid-source-index",
|
|
7851
|
-
|
|
8386
|
+
subjectId2,
|
|
7852
8387
|
"sourceIndex must be a non-negative integer locator",
|
|
7853
8388
|
"publish a non-negative sourceIndex without using it as identity"
|
|
7854
8389
|
);
|
|
@@ -7856,7 +8391,7 @@ function validateProducerContract(value) {
|
|
|
7856
8391
|
if (value.sourceKey === void 0 && value.sourceIndex !== void 0) {
|
|
7857
8392
|
return issue(
|
|
7858
8393
|
"missing-source-key",
|
|
7859
|
-
|
|
8394
|
+
subjectId2,
|
|
7860
8395
|
"sourceKey is required when an output declares sourceIndex",
|
|
7861
8396
|
"publish a stable semantic key; do not derive identity from sourceIndex"
|
|
7862
8397
|
);
|
|
@@ -7864,7 +8399,7 @@ function validateProducerContract(value) {
|
|
|
7864
8399
|
if ("compatiblePreviousKinds" in value && (!Array.isArray(value.compatiblePreviousKinds) || value.compatiblePreviousKinds.some((kind) => !hasText(kind)))) {
|
|
7865
8400
|
return issue(
|
|
7866
8401
|
"invalid-producer-fact",
|
|
7867
|
-
|
|
8402
|
+
subjectId2,
|
|
7868
8403
|
"compatiblePreviousKinds must be an array of non-empty kind strings",
|
|
7869
8404
|
"declare only producer-verified prior kinds that may preserve the GUID"
|
|
7870
8405
|
);
|
|
@@ -7949,7 +8484,7 @@ var meta_schema_default = {
|
|
|
7949
8484
|
source: {
|
|
7950
8485
|
type: "string",
|
|
7951
8486
|
minLength: 1,
|
|
7952
|
-
description: "Optional. Omit to derive the companion file in the same directory (strip .meta.json suffix from the meta filename).
|
|
8487
|
+
description: "Optional. Omit to derive the companion file in the same directory (strip .meta.json suffix from the meta filename). An explicit source is resolved relative to this sidecar."
|
|
7953
8488
|
},
|
|
7954
8489
|
importSettings: {
|
|
7955
8490
|
type: "object",
|
|
@@ -8090,11 +8625,11 @@ var pack_schema_default = {
|
|
|
8090
8625
|
$comment: "The ordinary durable consumer matrix is SCRIPTABLE_PACK_ASSET_KINDS in @forgeax/engine-pack/source. Pack kind fields remain open for registered producer extensions.",
|
|
8091
8626
|
type: "object",
|
|
8092
8627
|
additionalProperties: false,
|
|
8093
|
-
required: ["schemaVersion"
|
|
8628
|
+
required: ["schemaVersion"],
|
|
8094
8629
|
properties: {
|
|
8095
8630
|
schemaVersion: {
|
|
8096
8631
|
type: "string",
|
|
8097
|
-
enum: ["1.0.0", "2.0.0"]
|
|
8632
|
+
enum: ["1.0.0", "2.0.0", "3.0.0"]
|
|
8098
8633
|
},
|
|
8099
8634
|
kind: {
|
|
8100
8635
|
type: "string",
|
|
@@ -8116,12 +8651,58 @@ var pack_schema_default = {
|
|
|
8116
8651
|
items: { $ref: "#/$defs/diagnostic" }
|
|
8117
8652
|
},
|
|
8118
8653
|
assets: {
|
|
8119
|
-
|
|
8120
|
-
|
|
8121
|
-
|
|
8122
|
-
|
|
8654
|
+
oneOf: [
|
|
8655
|
+
{
|
|
8656
|
+
type: "array",
|
|
8657
|
+
items: { $ref: "#/$defs/asset" }
|
|
8658
|
+
},
|
|
8659
|
+
{ $ref: "#/$defs/authoringAssets" }
|
|
8660
|
+
]
|
|
8661
|
+
},
|
|
8662
|
+
parent: {
|
|
8663
|
+
$ref: "#/$defs/guid36",
|
|
8664
|
+
description: "Parent parameterized Pack packageId for one v3 instance."
|
|
8665
|
+
},
|
|
8666
|
+
values: {
|
|
8667
|
+
type: "object",
|
|
8668
|
+
additionalProperties: true,
|
|
8669
|
+
description: "Sparse shallow parameter overrides for one v3 instance."
|
|
8123
8670
|
}
|
|
8124
8671
|
},
|
|
8672
|
+
oneOf: [
|
|
8673
|
+
{
|
|
8674
|
+
required: ["kind", "assets"],
|
|
8675
|
+
properties: {
|
|
8676
|
+
schemaVersion: { enum: ["1.0.0", "2.0.0"] },
|
|
8677
|
+
kind: { const: "internal-text-package" },
|
|
8678
|
+
assets: { type: "array" },
|
|
8679
|
+
parent: false,
|
|
8680
|
+
values: false
|
|
8681
|
+
}
|
|
8682
|
+
},
|
|
8683
|
+
{
|
|
8684
|
+
required: ["packageId", "assets"],
|
|
8685
|
+
properties: {
|
|
8686
|
+
schemaVersion: { const: "3.0.0" },
|
|
8687
|
+
kind: false,
|
|
8688
|
+
packageId: { $ref: "#/$defs/guid36" },
|
|
8689
|
+
assets: { $ref: "#/$defs/authoringAssets" },
|
|
8690
|
+
parent: false,
|
|
8691
|
+
values: false
|
|
8692
|
+
}
|
|
8693
|
+
},
|
|
8694
|
+
{
|
|
8695
|
+
required: ["packageId", "parent", "values"],
|
|
8696
|
+
properties: {
|
|
8697
|
+
schemaVersion: { const: "3.0.0" },
|
|
8698
|
+
kind: false,
|
|
8699
|
+
packageId: { $ref: "#/$defs/guid36" },
|
|
8700
|
+
parent: { $ref: "#/$defs/guid36" },
|
|
8701
|
+
values: { type: "object" },
|
|
8702
|
+
assets: false
|
|
8703
|
+
}
|
|
8704
|
+
}
|
|
8705
|
+
],
|
|
8125
8706
|
allOf: [
|
|
8126
8707
|
{
|
|
8127
8708
|
if: {
|
|
@@ -8213,16 +8794,40 @@ var pack_schema_default = {
|
|
|
8213
8794
|
}
|
|
8214
8795
|
]
|
|
8215
8796
|
},
|
|
8216
|
-
|
|
8797
|
+
authoringAssets: {
|
|
8217
8798
|
type: "object",
|
|
8218
8799
|
additionalProperties: false,
|
|
8219
8800
|
patternProperties: {
|
|
8220
|
-
"^[
|
|
8221
|
-
$ref: "#/$defs/
|
|
8801
|
+
"^[a-z0-9][a-z0-9._-]*(/[a-z0-9][a-z0-9._-]*)*$": {
|
|
8802
|
+
$ref: "#/$defs/authoringAsset"
|
|
8222
8803
|
}
|
|
8223
8804
|
}
|
|
8224
8805
|
},
|
|
8225
|
-
|
|
8806
|
+
authoringAsset: {
|
|
8807
|
+
type: "object",
|
|
8808
|
+
additionalProperties: false,
|
|
8809
|
+
required: ["kind", "payload", "refs"],
|
|
8810
|
+
properties: {
|
|
8811
|
+
kind: { type: "string", minLength: 1 },
|
|
8812
|
+
name: { type: "string", minLength: 1 },
|
|
8813
|
+
payload: { type: "object" },
|
|
8814
|
+
refs: {
|
|
8815
|
+
type: "array",
|
|
8816
|
+
items: { $ref: "#/$defs/guid36" }
|
|
8817
|
+
},
|
|
8818
|
+
artifacts: { $ref: "#/$defs/artifacts" }
|
|
8819
|
+
}
|
|
8820
|
+
},
|
|
8821
|
+
artifacts: {
|
|
8822
|
+
type: "object",
|
|
8823
|
+
additionalProperties: false,
|
|
8824
|
+
patternProperties: {
|
|
8825
|
+
"^[A-Za-z0-9][A-Za-z0-9._/-]*$": {
|
|
8826
|
+
$ref: "#/$defs/artifactDescriptor"
|
|
8827
|
+
}
|
|
8828
|
+
}
|
|
8829
|
+
},
|
|
8830
|
+
artifactDescriptor: {
|
|
8226
8831
|
type: "object",
|
|
8227
8832
|
additionalProperties: false,
|
|
8228
8833
|
required: ["path", "mediaType"],
|
|
@@ -8379,50 +8984,51 @@ async function inventoryScriptablePackSource(sourcePath, initialSourceText) {
|
|
|
8379
8984
|
}
|
|
8380
8985
|
function serializeFailure(value) {
|
|
8381
8986
|
if (value !== null && typeof value === "object") {
|
|
8382
|
-
const
|
|
8987
|
+
const failure5 = value;
|
|
8383
8988
|
return {
|
|
8384
|
-
name:
|
|
8385
|
-
code:
|
|
8386
|
-
expected:
|
|
8387
|
-
actual:
|
|
8388
|
-
hint:
|
|
8389
|
-
detail:
|
|
8390
|
-
message:
|
|
8989
|
+
name: failure5.name,
|
|
8990
|
+
code: failure5.code,
|
|
8991
|
+
expected: failure5.expected,
|
|
8992
|
+
actual: failure5.actual,
|
|
8993
|
+
hint: failure5.hint,
|
|
8994
|
+
detail: failure5.detail,
|
|
8995
|
+
message: failure5.message
|
|
8391
8996
|
};
|
|
8392
8997
|
}
|
|
8393
8998
|
return { message: String(value) };
|
|
8394
8999
|
}
|
|
8395
9000
|
function hydrateFailure(value) {
|
|
8396
9001
|
if (value === null || typeof value !== "object") return value;
|
|
8397
|
-
const
|
|
8398
|
-
if (
|
|
9002
|
+
const failure5 = value;
|
|
9003
|
+
if (failure5.name === "AssetError" && typeof failure5.code === "string" && typeof failure5.expected === "string" && typeof failure5.hint === "string") {
|
|
8399
9004
|
const args = {
|
|
8400
|
-
code:
|
|
8401
|
-
expected:
|
|
8402
|
-
hint:
|
|
9005
|
+
code: failure5.code,
|
|
9006
|
+
expected: failure5.expected,
|
|
9007
|
+
hint: failure5.hint
|
|
8403
9008
|
};
|
|
8404
|
-
return
|
|
9009
|
+
return failure5.detail === void 0 ? new AssetError(args) : new AssetError({
|
|
8405
9010
|
...args,
|
|
8406
|
-
detail:
|
|
9011
|
+
detail: failure5.detail
|
|
8407
9012
|
});
|
|
8408
9013
|
}
|
|
8409
|
-
if (
|
|
9014
|
+
if (failure5.name === "ImportError" && typeof failure5.code === "string" && typeof failure5.expected === "string" && typeof failure5.hint === "string" && failure5.detail !== void 0) {
|
|
8410
9015
|
return new ImportError({
|
|
8411
|
-
code:
|
|
8412
|
-
expected:
|
|
8413
|
-
hint:
|
|
8414
|
-
detail:
|
|
8415
|
-
...typeof
|
|
9016
|
+
code: failure5.code,
|
|
9017
|
+
expected: failure5.expected,
|
|
9018
|
+
hint: failure5.hint,
|
|
9019
|
+
detail: failure5.detail,
|
|
9020
|
+
...typeof failure5.actual === "string" ? { actual: failure5.actual } : {}
|
|
8416
9021
|
});
|
|
8417
9022
|
}
|
|
8418
|
-
if (typeof
|
|
8419
|
-
const error = new Error(
|
|
8420
|
-
if (typeof
|
|
9023
|
+
if (typeof failure5.message === "string") {
|
|
9024
|
+
const error = new Error(failure5.message);
|
|
9025
|
+
if (typeof failure5.name === "string") error.name = failure5.name;
|
|
8421
9026
|
return error;
|
|
8422
9027
|
}
|
|
8423
9028
|
return value;
|
|
8424
9029
|
}
|
|
8425
9030
|
var WorkerScriptablePackExecutor = class {
|
|
9031
|
+
supportsParameterizedContext = true;
|
|
8426
9032
|
worker;
|
|
8427
9033
|
compileRoot;
|
|
8428
9034
|
nextBuildId = 0;
|
|
@@ -8450,7 +9056,7 @@ var WorkerScriptablePackExecutor = class {
|
|
|
8450
9056
|
resolveLoad({
|
|
8451
9057
|
default: value.definition === void 0 ? void 0 : {
|
|
8452
9058
|
...value.definition,
|
|
8453
|
-
build: (
|
|
9059
|
+
build: (readByGuid, context) => this.runBuild({ readByGuid }, context)
|
|
8454
9060
|
}
|
|
8455
9061
|
});
|
|
8456
9062
|
} else if (value.kind === "load-threw") {
|
|
@@ -8482,7 +9088,7 @@ var WorkerScriptablePackExecutor = class {
|
|
|
8482
9088
|
})();
|
|
8483
9089
|
return this.disposal;
|
|
8484
9090
|
}
|
|
8485
|
-
runBuild(reader) {
|
|
9091
|
+
runBuild(reader, context) {
|
|
8486
9092
|
const worker = this.worker;
|
|
8487
9093
|
if (worker === void 0) return Promise.reject(new Error("ScriptablePack worker is closed"));
|
|
8488
9094
|
if (this.build !== void 0)
|
|
@@ -8490,7 +9096,7 @@ var WorkerScriptablePackExecutor = class {
|
|
|
8490
9096
|
const id = this.nextBuildId++;
|
|
8491
9097
|
return new Promise((resolveBuild, rejectBuild) => {
|
|
8492
9098
|
this.build = { id, reader, resolve: resolveBuild, reject: rejectBuild };
|
|
8493
|
-
worker.postMessage({ kind: "build", buildId: id });
|
|
9099
|
+
worker.postMessage({ kind: "build", buildId: id, context });
|
|
8494
9100
|
});
|
|
8495
9101
|
}
|
|
8496
9102
|
onMessage(message) {
|
|
@@ -8523,11 +9129,11 @@ function scriptablePackWorkerUrl() {
|
|
|
8523
9129
|
const bundledWorker = new URL("./scriptable-pack-worker.mjs", import.meta.url);
|
|
8524
9130
|
return existsSync(fileURLToPath(bundledWorker)) ? bundledWorker : new URL("../dist/scriptable-pack-worker.mjs", import.meta.url);
|
|
8525
9131
|
}
|
|
8526
|
-
function
|
|
8527
|
-
return
|
|
8528
|
-
code: "pack-
|
|
8529
|
-
expected: "a trusted
|
|
8530
|
-
hint: "repair the module
|
|
9132
|
+
function parameterizedLoadFailure(sourcePath, reason, phase, diagnostic, timeoutMs) {
|
|
9133
|
+
return {
|
|
9134
|
+
code: "pack-parameter-invalid",
|
|
9135
|
+
expected: "a trusted Pack v2 authoring module with a valid default export",
|
|
9136
|
+
hint: "repair the source module or its build timeout, then inspect the Pack again",
|
|
8531
9137
|
detail: {
|
|
8532
9138
|
sourcePath,
|
|
8533
9139
|
reason,
|
|
@@ -8535,70 +9141,71 @@ function loadFailure(sourcePath, reason, phase, diagnostic, timeoutMs) {
|
|
|
8535
9141
|
diagnostic,
|
|
8536
9142
|
...timeoutMs === void 0 ? {} : { timeoutMs }
|
|
8537
9143
|
}
|
|
8538
|
-
});
|
|
8539
|
-
}
|
|
8540
|
-
function buildTimeoutFailure(sourcePath, timeoutMs) {
|
|
8541
|
-
return {
|
|
8542
|
-
code: "pack-source-load-failed",
|
|
8543
|
-
expected: "a ScriptablePack build to settle within the configured build timeout",
|
|
8544
|
-
hint: "repair the authored build, then retry through a fresh ScriptablePack generation",
|
|
8545
|
-
detail: {
|
|
8546
|
-
sourcePath,
|
|
8547
|
-
reason: "timeout",
|
|
8548
|
-
phase: "build",
|
|
8549
|
-
timeoutMs,
|
|
8550
|
-
diagnostic: `ScriptablePack build exceeded ${timeoutMs}ms`
|
|
8551
|
-
}
|
|
8552
9144
|
};
|
|
8553
9145
|
}
|
|
8554
|
-
async function
|
|
9146
|
+
async function loadParameterizedScriptablePack(sourcePath, options = {}) {
|
|
8555
9147
|
const timeoutMs = options.timeoutMs ?? 15e3;
|
|
8556
9148
|
const buildTimeoutMs = options.buildTimeoutMs ?? 5e3;
|
|
8557
9149
|
const executor = options.executor ?? new WorkerScriptablePackExecutor();
|
|
8558
9150
|
let disposeReason;
|
|
8559
9151
|
let timeout;
|
|
8560
9152
|
try {
|
|
8561
|
-
const timeoutSignal = /* @__PURE__ */ Symbol("
|
|
9153
|
+
const timeoutSignal = /* @__PURE__ */ Symbol("parameterized-pack-module-timeout");
|
|
8562
9154
|
const loaded = await Promise.race([
|
|
8563
9155
|
executor.load(sourcePath),
|
|
8564
|
-
new Promise((
|
|
8565
|
-
timeout = setTimeout(() =>
|
|
9156
|
+
new Promise((resolve4) => {
|
|
9157
|
+
timeout = setTimeout(() => resolve4(timeoutSignal), timeoutMs);
|
|
8566
9158
|
})
|
|
8567
9159
|
]);
|
|
8568
9160
|
if (loaded === timeoutSignal) {
|
|
8569
9161
|
disposeReason = "timeout";
|
|
8570
|
-
return
|
|
8571
|
-
|
|
8572
|
-
|
|
8573
|
-
|
|
8574
|
-
|
|
8575
|
-
|
|
9162
|
+
return err(
|
|
9163
|
+
parameterizedLoadFailure(
|
|
9164
|
+
sourcePath,
|
|
9165
|
+
"timeout",
|
|
9166
|
+
"module-load",
|
|
9167
|
+
`Pack module initialization exceeded ${timeoutMs}ms`,
|
|
9168
|
+
timeoutMs
|
|
9169
|
+
)
|
|
8576
9170
|
);
|
|
8577
9171
|
}
|
|
8578
9172
|
const moduleValue = loaded !== null && typeof loaded === "object" && "default" in loaded ? loaded.default : void 0;
|
|
8579
|
-
const validated =
|
|
9173
|
+
const validated = validatePackDefinition(moduleValue, sourcePath);
|
|
8580
9174
|
if (!validated.ok) {
|
|
8581
9175
|
disposeReason = "failure";
|
|
8582
9176
|
return validated;
|
|
8583
9177
|
}
|
|
8584
9178
|
if (options.metadataOnly === true) {
|
|
8585
9179
|
disposeReason = "complete";
|
|
8586
|
-
return validated;
|
|
9180
|
+
return ok(validated.value);
|
|
8587
9181
|
}
|
|
8588
9182
|
const definition = validated.value;
|
|
9183
|
+
const build = definition.build;
|
|
8589
9184
|
return ok({
|
|
8590
9185
|
...definition,
|
|
8591
|
-
build: async (
|
|
9186
|
+
build: async (context) => {
|
|
8592
9187
|
let buildTimedOut = false;
|
|
8593
9188
|
let buildTimeout;
|
|
8594
|
-
const timeoutResult = err(
|
|
9189
|
+
const timeoutResult = err(
|
|
9190
|
+
parameterizedLoadFailure(
|
|
9191
|
+
sourcePath,
|
|
9192
|
+
"timeout",
|
|
9193
|
+
"build",
|
|
9194
|
+
`ScriptablePack build exceeded ${buildTimeoutMs}ms`,
|
|
9195
|
+
buildTimeoutMs
|
|
9196
|
+
)
|
|
9197
|
+
);
|
|
8595
9198
|
try {
|
|
9199
|
+
const invocation = "supportsParameterizedContext" in executor && executor.supportsParameterizedContext === true ? build(context.readByGuid, {
|
|
9200
|
+
packageId: [...context.packageId],
|
|
9201
|
+
..."values" in context && context.values !== void 0 ? { values: context.values } : {}
|
|
9202
|
+
}) : definition.build(context);
|
|
8596
9203
|
const built = await Promise.race([
|
|
8597
|
-
Promise.resolve(
|
|
8598
|
-
new Promise((
|
|
9204
|
+
Promise.resolve(invocation),
|
|
9205
|
+
new Promise((resolve4) => {
|
|
8599
9206
|
buildTimeout = setTimeout(() => {
|
|
8600
9207
|
buildTimedOut = true;
|
|
8601
|
-
|
|
9208
|
+
resolve4(timeoutResult);
|
|
8602
9209
|
}, buildTimeoutMs);
|
|
8603
9210
|
})
|
|
8604
9211
|
]);
|
|
@@ -8617,9 +9224,15 @@ async function loadScriptablePack(sourcePath, options = {}) {
|
|
|
8617
9224
|
}
|
|
8618
9225
|
});
|
|
8619
9226
|
} catch (error) {
|
|
8620
|
-
const diagnostic = error instanceof Error ? error.message : String(error);
|
|
8621
9227
|
disposeReason = "failure";
|
|
8622
|
-
return
|
|
9228
|
+
return err(
|
|
9229
|
+
parameterizedLoadFailure(
|
|
9230
|
+
sourcePath,
|
|
9231
|
+
"module-load",
|
|
9232
|
+
"module-load",
|
|
9233
|
+
error instanceof Error ? error.message : String(error)
|
|
9234
|
+
)
|
|
9235
|
+
);
|
|
8623
9236
|
} finally {
|
|
8624
9237
|
if (timeout !== void 0) clearTimeout(timeout);
|
|
8625
9238
|
if (disposeReason !== void 0) await executor.dispose?.(disposeReason);
|
|
@@ -8633,11 +9246,15 @@ function ok4(value) {
|
|
|
8633
9246
|
function packErr(error) {
|
|
8634
9247
|
return { ok: false, error };
|
|
8635
9248
|
}
|
|
9249
|
+
function record(value) {
|
|
9250
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
9251
|
+
}
|
|
8636
9252
|
var STANDARD_SCRIPTABLE_PACK_SCAN_OPTIONS = Object.freeze(
|
|
8637
9253
|
{}
|
|
8638
9254
|
);
|
|
8639
9255
|
var BLACKLIST = /* @__PURE__ */ new Set([
|
|
8640
9256
|
"node_modules",
|
|
9257
|
+
"__tests__",
|
|
8641
9258
|
".forgeax-harness",
|
|
8642
9259
|
".forgeax",
|
|
8643
9260
|
".git",
|
|
@@ -8740,10 +9357,87 @@ async function scanValidated(roots, opts = {}, capture) {
|
|
|
8740
9357
|
const scriptablePaths = rawPaths.filter((p) => p.endsWith(".pack.ts"));
|
|
8741
9358
|
const guidToPath = /* @__PURE__ */ new Map();
|
|
8742
9359
|
const packRefs = /* @__PURE__ */ new Map();
|
|
9360
|
+
const packageIdToPath = /* @__PURE__ */ new Map();
|
|
9361
|
+
const packageKind = /* @__PURE__ */ new Map();
|
|
9362
|
+
const instanceParents = [];
|
|
9363
|
+
function registerPackage(packageId2, path, kind) {
|
|
9364
|
+
if (packageId2 === void 0) return void 0;
|
|
9365
|
+
const normalized = packageId2.toLowerCase();
|
|
9366
|
+
const existing = packageIdToPath.get(normalized);
|
|
9367
|
+
if (existing !== void 0) {
|
|
9368
|
+
return makePackError("pack-guid-collision", {
|
|
9369
|
+
paths: [existing, path],
|
|
9370
|
+
guid: normalized
|
|
9371
|
+
});
|
|
9372
|
+
}
|
|
9373
|
+
packageIdToPath.set(normalized, path);
|
|
9374
|
+
packageKind.set(normalized, kind);
|
|
9375
|
+
return void 0;
|
|
9376
|
+
}
|
|
8743
9377
|
for (const packPath of packPaths) {
|
|
8744
9378
|
const loaded = await readValidatedJson(packPath, "pack-malformed-pack", validatePack);
|
|
8745
9379
|
if (!loaded.ok) return loaded;
|
|
8746
9380
|
const { raw, parsed } = loaded.value;
|
|
9381
|
+
if (record(parsed) && parsed.schemaVersion === "3.0.0") {
|
|
9382
|
+
const authoring = parseParameterizedPackJson(parsed);
|
|
9383
|
+
if (!authoring.ok) {
|
|
9384
|
+
return packErr(
|
|
9385
|
+
makePackError("pack-malformed-pack", {
|
|
9386
|
+
path: packPath,
|
|
9387
|
+
ajvErrors: [{ instancePath: "", message: authoring.error.code }]
|
|
9388
|
+
})
|
|
9389
|
+
);
|
|
9390
|
+
}
|
|
9391
|
+
const packageId2 = authoring.value.packageId;
|
|
9392
|
+
const packageCollision2 = registerPackage(
|
|
9393
|
+
PackageId.format(packageId2),
|
|
9394
|
+
packPath,
|
|
9395
|
+
authoring.value.format
|
|
9396
|
+
);
|
|
9397
|
+
if (packageCollision2 !== void 0) return packErr(packageCollision2);
|
|
9398
|
+
if (authoring.value.format === "instance") {
|
|
9399
|
+
instanceParents.push({
|
|
9400
|
+
path: packPath,
|
|
9401
|
+
packageId: PackageId.format(authoring.value.packageId),
|
|
9402
|
+
parent: PackageId.format(authoring.value.parent)
|
|
9403
|
+
});
|
|
9404
|
+
} else {
|
|
9405
|
+
const projected = projectDirectPackJson(authoring.value);
|
|
9406
|
+
if (!projected.ok) {
|
|
9407
|
+
return packErr(
|
|
9408
|
+
makePackError("pack-malformed-pack", {
|
|
9409
|
+
path: packPath,
|
|
9410
|
+
ajvErrors: [{ instancePath: "/assets", message: projected.error.code }]
|
|
9411
|
+
})
|
|
9412
|
+
);
|
|
9413
|
+
}
|
|
9414
|
+
for (const asset of projected.value.assets) {
|
|
9415
|
+
const normalizedGuid = asset.guid.toLowerCase();
|
|
9416
|
+
const existing = guidToPath.get(normalizedGuid);
|
|
9417
|
+
if (existing !== void 0) {
|
|
9418
|
+
return packErr(
|
|
9419
|
+
makePackError("pack-guid-collision", {
|
|
9420
|
+
paths: [existing, packPath],
|
|
9421
|
+
guid: normalizedGuid
|
|
9422
|
+
})
|
|
9423
|
+
);
|
|
9424
|
+
}
|
|
9425
|
+
guidToPath.set(normalizedGuid, packPath);
|
|
9426
|
+
packRefs.set(normalizedGuid, [
|
|
9427
|
+
...asset.refs.map((ref) => ref.toLowerCase()),
|
|
9428
|
+
...extractMountSourceGuids(asset)
|
|
9429
|
+
]);
|
|
9430
|
+
}
|
|
9431
|
+
}
|
|
9432
|
+
capture?.declarations.set(packPath, {
|
|
9433
|
+
format: "pack.json",
|
|
9434
|
+
sourcePath: packPath,
|
|
9435
|
+
sourceRevision: `sha256:${createHash("sha256").update(raw).digest("hex")}`,
|
|
9436
|
+
sourceText: raw,
|
|
9437
|
+
value: parsed
|
|
9438
|
+
});
|
|
9439
|
+
continue;
|
|
9440
|
+
}
|
|
8747
9441
|
const packageContract = validateProducerContract(parsed);
|
|
8748
9442
|
if (!packageContract.ok) {
|
|
8749
9443
|
return packErr(
|
|
@@ -8754,6 +9448,8 @@ async function scanValidated(roots, opts = {}, capture) {
|
|
|
8754
9448
|
);
|
|
8755
9449
|
}
|
|
8756
9450
|
const packObj = parsed;
|
|
9451
|
+
const packageCollision = registerPackage(packObj.packageId, packPath, "legacy");
|
|
9452
|
+
if (packageCollision !== void 0) return packErr(packageCollision);
|
|
8757
9453
|
for (const asset of packObj.assets) {
|
|
8758
9454
|
if (asset.kind === "particle-effect" && asset.execution === "direct" && (asset.refs.length > 0 || Object.keys(asset.artifacts ?? {}).length > 0)) {
|
|
8759
9455
|
return packErr(
|
|
@@ -8844,7 +9540,6 @@ async function scanValidated(roots, opts = {}, capture) {
|
|
|
8844
9540
|
value: packObj
|
|
8845
9541
|
});
|
|
8846
9542
|
}
|
|
8847
|
-
const { paths: assetPaths } = loadAssetConfig(process.cwd());
|
|
8848
9543
|
for (const metaPath of metaPaths) {
|
|
8849
9544
|
const loaded = await readValidatedJson(metaPath, "pack-malformed-meta", validateMeta);
|
|
8850
9545
|
if (!loaded.ok) return loaded;
|
|
@@ -8859,6 +9554,8 @@ async function scanValidated(roots, opts = {}, capture) {
|
|
|
8859
9554
|
);
|
|
8860
9555
|
}
|
|
8861
9556
|
const metaObj = parsed;
|
|
9557
|
+
const packageCollision = registerPackage(metaObj.packageId, metaPath, "legacy");
|
|
9558
|
+
if (packageCollision !== void 0) return packErr(packageCollision);
|
|
8862
9559
|
capture?.declarations.set(metaPath, {
|
|
8863
9560
|
format: "meta.json",
|
|
8864
9561
|
sourcePath: metaPath,
|
|
@@ -8898,11 +9595,7 @@ async function scanValidated(roots, opts = {}, capture) {
|
|
|
8898
9595
|
);
|
|
8899
9596
|
}
|
|
8900
9597
|
}
|
|
8901
|
-
const
|
|
8902
|
-
if (!sourceResolved.ok) {
|
|
8903
|
-
return packErr(sourceResolved.error);
|
|
8904
|
-
}
|
|
8905
|
-
const expectedSourcePath = sourceResolved.value;
|
|
9598
|
+
const expectedSourcePath = resolveAssetSource(metaPath, metaObj.source);
|
|
8906
9599
|
try {
|
|
8907
9600
|
await stat(expectedSourcePath);
|
|
8908
9601
|
} catch {
|
|
@@ -8922,23 +9615,24 @@ async function scanValidated(roots, opts = {}, capture) {
|
|
|
8922
9615
|
return packErr(
|
|
8923
9616
|
makePackError("pack-malformed-meta", {
|
|
8924
9617
|
path: sourcePath,
|
|
8925
|
-
ajvErrors: [{ instancePath: "", message: "
|
|
9618
|
+
ajvErrors: [{ instancePath: "", message: "Pack source read failed" }]
|
|
8926
9619
|
})
|
|
8927
9620
|
);
|
|
8928
9621
|
}
|
|
8929
|
-
const
|
|
9622
|
+
const loaderOptions = {
|
|
8930
9623
|
...opts.scriptablePack ?? {},
|
|
8931
9624
|
...capture === void 0 ? { metadataOnly: true } : {}
|
|
8932
|
-
}
|
|
9625
|
+
};
|
|
9626
|
+
const loaded = await loadParameterizedScriptablePack(sourcePath, loaderOptions);
|
|
8933
9627
|
if (!loaded.ok) {
|
|
8934
|
-
const diagnostic =
|
|
9628
|
+
const diagnostic = loaded.error.detail.diagnostic;
|
|
8935
9629
|
return packErr(
|
|
8936
9630
|
makePackError("pack-malformed-meta", {
|
|
8937
9631
|
path: sourcePath,
|
|
8938
9632
|
ajvErrors: [
|
|
8939
9633
|
{
|
|
8940
9634
|
instancePath: "",
|
|
8941
|
-
message: diagnostic ===
|
|
9635
|
+
message: typeof diagnostic === "string" ? `${loaded.error.code}: ${diagnostic}` : loaded.error.code
|
|
8942
9636
|
}
|
|
8943
9637
|
]
|
|
8944
9638
|
})
|
|
@@ -8951,41 +9645,81 @@ async function scanValidated(roots, opts = {}, capture) {
|
|
|
8951
9645
|
return packErr(
|
|
8952
9646
|
makePackError("pack-malformed-meta", {
|
|
8953
9647
|
path: sourcePath,
|
|
8954
|
-
ajvErrors: [{ instancePath: "", message: "
|
|
8955
|
-
})
|
|
8956
|
-
);
|
|
8957
|
-
}
|
|
8958
|
-
const meta = projectScriptablePackMeta(loaded.value, sourcePath);
|
|
8959
|
-
const topology = validateProducerOutputs(meta.subAssets);
|
|
8960
|
-
if (!topology.ok) {
|
|
8961
|
-
return packErr(
|
|
8962
|
-
makePackError("pack-malformed-meta", {
|
|
8963
|
-
path: sourcePath,
|
|
8964
|
-
ajvErrors: [{ instancePath: "/subAssets", message: topology.error.code }]
|
|
9648
|
+
ajvErrors: [{ instancePath: "", message: "Pack source closure read failed" }]
|
|
8965
9649
|
})
|
|
8966
9650
|
);
|
|
8967
9651
|
}
|
|
8968
|
-
const
|
|
9652
|
+
const packageCollision = registerPackage(
|
|
9653
|
+
PackageId.format(loaded.value.packageId),
|
|
9654
|
+
sourcePath,
|
|
9655
|
+
"parameterized"
|
|
9656
|
+
);
|
|
9657
|
+
if (packageCollision !== void 0) return packErr(packageCollision);
|
|
9658
|
+
const meta = projectParameterizedPackMeta(loaded.value, sourcePath);
|
|
9659
|
+
capture?.declarations.set(sourcePath, {
|
|
9660
|
+
format: "pack.ts-parameterized",
|
|
8969
9661
|
sourcePath,
|
|
8970
9662
|
sourceRevision: `sha256:${createHash("sha256").update(source).digest("hex")}`,
|
|
8971
|
-
meta,
|
|
9663
|
+
value: meta,
|
|
8972
9664
|
definition: loaded.value,
|
|
8973
9665
|
sourceClosure
|
|
8974
|
-
};
|
|
8975
|
-
capture?.declarations.set(sourcePath, {
|
|
8976
|
-
format: "pack.ts",
|
|
8977
|
-
...declaration,
|
|
8978
|
-
value: meta
|
|
8979
9666
|
});
|
|
8980
|
-
|
|
8981
|
-
|
|
8982
|
-
|
|
8983
|
-
|
|
9667
|
+
}
|
|
9668
|
+
const parentByPackageId = new Map(
|
|
9669
|
+
instanceParents.map((instance) => [instance.packageId.toLowerCase(), instance])
|
|
9670
|
+
);
|
|
9671
|
+
for (const instance of instanceParents) {
|
|
9672
|
+
const parentId = instance.parent.toLowerCase();
|
|
9673
|
+
const parentPath = packageIdToPath.get(parentId);
|
|
9674
|
+
if (parentPath === void 0) {
|
|
9675
|
+
return packErr(
|
|
9676
|
+
makePackError("pack-malformed-pack", {
|
|
9677
|
+
path: instance.path,
|
|
9678
|
+
reason: "pack-parent-not-found",
|
|
9679
|
+
ajvErrors: [
|
|
9680
|
+
{
|
|
9681
|
+
instancePath: "/parent",
|
|
9682
|
+
message: `parent packageId ${instance.parent} was not found`
|
|
9683
|
+
}
|
|
9684
|
+
]
|
|
9685
|
+
})
|
|
9686
|
+
);
|
|
9687
|
+
}
|
|
9688
|
+
const kind = packageKind.get(parentId);
|
|
9689
|
+
if (kind !== "parameterized" && kind !== "instance") {
|
|
9690
|
+
return packErr(
|
|
9691
|
+
makePackError("pack-malformed-pack", {
|
|
9692
|
+
path: instance.path,
|
|
9693
|
+
reason: "pack-parent-not-parameterized",
|
|
9694
|
+
ajvErrors: [
|
|
9695
|
+
{
|
|
9696
|
+
instancePath: "/parent",
|
|
9697
|
+
message: `parent ${instance.parent} is not a parameterized Pack`
|
|
9698
|
+
}
|
|
9699
|
+
]
|
|
9700
|
+
})
|
|
9701
|
+
);
|
|
9702
|
+
}
|
|
9703
|
+
}
|
|
9704
|
+
for (const instance of instanceParents) {
|
|
9705
|
+
const chain = /* @__PURE__ */ new Set();
|
|
9706
|
+
let current = instance.packageId.toLowerCase();
|
|
9707
|
+
while (true) {
|
|
9708
|
+
if (chain.has(current)) {
|
|
8984
9709
|
return packErr(
|
|
8985
|
-
makePackError("pack-
|
|
9710
|
+
makePackError("pack-malformed-pack", {
|
|
9711
|
+
path: instance.path,
|
|
9712
|
+
reason: "pack-parent-cycle",
|
|
9713
|
+
ajvErrors: [
|
|
9714
|
+
{ instancePath: "/parent", message: `parent chain repeats packageId ${current}` }
|
|
9715
|
+
]
|
|
9716
|
+
})
|
|
8986
9717
|
);
|
|
8987
9718
|
}
|
|
8988
|
-
|
|
9719
|
+
chain.add(current);
|
|
9720
|
+
const next = parentByPackageId.get(current);
|
|
9721
|
+
if (next === void 0) break;
|
|
9722
|
+
current = next.parent.toLowerCase();
|
|
8989
9723
|
}
|
|
8990
9724
|
}
|
|
8991
9725
|
const visited = /* @__PURE__ */ new Set();
|
|
@@ -9029,6 +9763,38 @@ async function scanInventory(roots, opts = {}) {
|
|
|
9029
9763
|
for (const sourcePath of scanned.value) {
|
|
9030
9764
|
const declaration = declarations.get(sourcePath);
|
|
9031
9765
|
if (declaration?.format !== "pack.json") continue;
|
|
9766
|
+
if (declaration.value.schemaVersion === "3.0.0") {
|
|
9767
|
+
const parsed = parseParameterizedPackJson(declaration.value);
|
|
9768
|
+
if (!parsed.ok) {
|
|
9769
|
+
return packErr(
|
|
9770
|
+
makePackError("pack-malformed-pack", {
|
|
9771
|
+
path: sourcePath,
|
|
9772
|
+
ajvErrors: [{ instancePath: "", message: parsed.error.code }]
|
|
9773
|
+
})
|
|
9774
|
+
);
|
|
9775
|
+
}
|
|
9776
|
+
if (parsed.value.format !== "direct") continue;
|
|
9777
|
+
const projected = projectDirectPackJson(parsed.value);
|
|
9778
|
+
if (!projected.ok) {
|
|
9779
|
+
return packErr(
|
|
9780
|
+
makePackError("pack-malformed-pack", {
|
|
9781
|
+
path: sourcePath,
|
|
9782
|
+
ajvErrors: [{ instancePath: "/assets", message: projected.error.code }]
|
|
9783
|
+
})
|
|
9784
|
+
);
|
|
9785
|
+
}
|
|
9786
|
+
for (const [index, asset] of projected.value.assets.entries()) {
|
|
9787
|
+
inventory.push({
|
|
9788
|
+
guid: asset.guid,
|
|
9789
|
+
kind: asset.kind,
|
|
9790
|
+
sourcePath,
|
|
9791
|
+
sourceRevision: declaration.sourceRevision,
|
|
9792
|
+
sourceKey: asset.sourceKey,
|
|
9793
|
+
sourceIndex: index
|
|
9794
|
+
});
|
|
9795
|
+
}
|
|
9796
|
+
continue;
|
|
9797
|
+
}
|
|
9032
9798
|
for (const [index, asset] of declaration.value.assets.entries()) {
|
|
9033
9799
|
inventory.push({
|
|
9034
9800
|
guid: asset.guid,
|
|
@@ -9070,28 +9836,18 @@ function unsupportedPolicyError(path, importer, policy) {
|
|
|
9070
9836
|
subjects: [path]
|
|
9071
9837
|
};
|
|
9072
9838
|
}
|
|
9073
|
-
function projectMeta(rawPath, cwd, base,
|
|
9839
|
+
function projectMeta(rawPath, cwd, base, importerPolicy, sourceDeclaration, sourceIdentityFor) {
|
|
9074
9840
|
const meta = sourceDeclaration.value;
|
|
9075
9841
|
const policy = importerPolicy(meta.importer);
|
|
9076
9842
|
if (policy.disposition !== "publish") {
|
|
9077
9843
|
return { entries: [], error: unsupportedPolicyError(rawPath, meta.importer, policy) };
|
|
9078
9844
|
}
|
|
9079
|
-
const resolved = resolveAssetSource(rawPath, meta.source
|
|
9080
|
-
|
|
9081
|
-
return {
|
|
9082
|
-
entries: [],
|
|
9083
|
-
error: {
|
|
9084
|
-
code: "catalog-meta-schema-invalid",
|
|
9085
|
-
path: rawPath,
|
|
9086
|
-
message: `source resolution failed: ${resolved.error.code} - ${resolved.error.hint}`
|
|
9087
|
-
}
|
|
9088
|
-
};
|
|
9089
|
-
}
|
|
9090
|
-
const sourcePath = catalogSourcePathFor(cwd, resolved.value, sourceIdentityFor);
|
|
9845
|
+
const resolved = resolveAssetSource(rawPath, meta.source);
|
|
9846
|
+
const sourcePath = catalogSourcePathFor(cwd, resolved, sourceIdentityFor);
|
|
9091
9847
|
const packageUrl2 = `${base}/__forgeax-ddc/${meta.subAssets[0]?.guid?.toLowerCase() ?? "pack"}.pack.json`;
|
|
9092
9848
|
const declaration = {
|
|
9093
9849
|
importer: meta.importer,
|
|
9094
|
-
source: resolved
|
|
9850
|
+
source: resolved,
|
|
9095
9851
|
sourceRevision: sourceDeclaration.sourceRevision,
|
|
9096
9852
|
...meta.packageId === void 0 ? {} : { packageId: meta.packageId },
|
|
9097
9853
|
...meta.provenance === void 0 ? {} : { provenance: meta.provenance },
|
|
@@ -9125,23 +9881,13 @@ function projectMeta(rawPath, cwd, base, assetPaths, importerPolicy, sourceDecla
|
|
|
9125
9881
|
sourcePath,
|
|
9126
9882
|
packageUrl2,
|
|
9127
9883
|
meta.subAssets,
|
|
9128
|
-
(output) => deriveAssetName(resolved
|
|
9884
|
+
(output) => deriveAssetName(resolved, meta.subAssets.length, output.name)
|
|
9129
9885
|
)
|
|
9130
9886
|
};
|
|
9131
9887
|
}
|
|
9132
|
-
function projectSource(path, cwd, base,
|
|
9133
|
-
if (sourceDeclaration.format === "pack.ts") {
|
|
9134
|
-
|
|
9135
|
-
const anchorGuid = meta.subAssets.map((asset) => asset.guid.toLowerCase()).sort()[0];
|
|
9136
|
-
return anchorGuid === void 0 ? { entries: [] } : {
|
|
9137
|
-
entries: projectExternalCatalogEntries(
|
|
9138
|
-
meta,
|
|
9139
|
-
catalogSourcePathFor(cwd, path, sourceIdentityFor),
|
|
9140
|
-
`${base}/__forgeax-ddc/${anchorGuid}.pack.json`,
|
|
9141
|
-
meta.subAssets,
|
|
9142
|
-
(output) => deriveAssetName(path, meta.subAssets.length, output.name)
|
|
9143
|
-
)
|
|
9144
|
-
};
|
|
9888
|
+
function projectSource(path, cwd, base, importerPolicy, visibility, sourceDeclaration, declarations, sourceIdentityFor) {
|
|
9889
|
+
if (sourceDeclaration.format === "pack.ts-parameterized") {
|
|
9890
|
+
return { entries: [] };
|
|
9145
9891
|
}
|
|
9146
9892
|
if (sourceDeclaration.format === "meta.json") {
|
|
9147
9893
|
const policy = importerPolicy(sourceDeclaration.value.importer);
|
|
@@ -9156,7 +9902,6 @@ function projectSource(path, cwd, base, assetPaths, importerPolicy, visibility,
|
|
|
9156
9902
|
path,
|
|
9157
9903
|
cwd,
|
|
9158
9904
|
base,
|
|
9159
|
-
assetPaths,
|
|
9160
9905
|
importerPolicy,
|
|
9161
9906
|
sourceDeclaration,
|
|
9162
9907
|
sourceIdentityFor
|
|
@@ -9166,6 +9911,57 @@ function projectSource(path, cwd, base, assetPaths, importerPolicy, visibility,
|
|
|
9166
9911
|
}
|
|
9167
9912
|
const parsed = sourceDeclaration.value;
|
|
9168
9913
|
const sourcePath = catalogSourcePathFor(cwd, path, sourceIdentityFor);
|
|
9914
|
+
if (parsed.schemaVersion === "3.0.0") {
|
|
9915
|
+
const authoring = parseParameterizedPackJson(parsed);
|
|
9916
|
+
if (!authoring.ok) {
|
|
9917
|
+
return {
|
|
9918
|
+
entries: [],
|
|
9919
|
+
error: {
|
|
9920
|
+
code: "catalog-meta-schema-invalid",
|
|
9921
|
+
path,
|
|
9922
|
+
message: `v3 Pack parse failed: ${authoring.error.code}`,
|
|
9923
|
+
expected: "a valid direct or instance v3 Pack document",
|
|
9924
|
+
actual: authoring.error.code,
|
|
9925
|
+
hint: authoring.error.hint,
|
|
9926
|
+
subjects: [path]
|
|
9927
|
+
}
|
|
9928
|
+
};
|
|
9929
|
+
}
|
|
9930
|
+
if (authoring.value.format !== "direct") return { entries: [] };
|
|
9931
|
+
const projected = projectDirectPackJson(authoring.value);
|
|
9932
|
+
if (!projected.ok) {
|
|
9933
|
+
return {
|
|
9934
|
+
entries: [],
|
|
9935
|
+
error: {
|
|
9936
|
+
code: "catalog-meta-schema-invalid",
|
|
9937
|
+
path,
|
|
9938
|
+
message: `v3 Pack projection failed: ${projected.error.code}`,
|
|
9939
|
+
expected: "direct v3 assets to derive stable AssetGuids",
|
|
9940
|
+
actual: projected.error.code,
|
|
9941
|
+
hint: projected.error.hint,
|
|
9942
|
+
subjects: [path]
|
|
9943
|
+
}
|
|
9944
|
+
};
|
|
9945
|
+
}
|
|
9946
|
+
const provenance2 = { provider: "pack", version: "3.0.0" };
|
|
9947
|
+
return {
|
|
9948
|
+
entries: projectPackageCatalog(
|
|
9949
|
+
projected.value.assets.map((asset, sourceIndex) => ({
|
|
9950
|
+
guid: asset.guid,
|
|
9951
|
+
kind: asset.kind,
|
|
9952
|
+
sourcePath,
|
|
9953
|
+
sourceIndex,
|
|
9954
|
+
sourceKey: asset.sourceKey,
|
|
9955
|
+
refs: asset.refs,
|
|
9956
|
+
execution: "direct",
|
|
9957
|
+
packageId: projected.value.packageId,
|
|
9958
|
+
provenance: provenance2,
|
|
9959
|
+
name: deriveAssetName(path, projected.value.assets.length, asset.name)
|
|
9960
|
+
})),
|
|
9961
|
+
`${base}/${sourcePath}`
|
|
9962
|
+
)
|
|
9963
|
+
};
|
|
9964
|
+
}
|
|
9169
9965
|
const provenance = parsed.provenance ?? { provider: "pack", version: parsed.schemaVersion };
|
|
9170
9966
|
return {
|
|
9171
9967
|
entries: projectPackageCatalog(
|
|
@@ -9216,7 +10012,6 @@ async function buildCatalogProjection(roots, options) {
|
|
|
9216
10012
|
return empty("degraded", [error]);
|
|
9217
10013
|
}
|
|
9218
10014
|
const { paths, declarations: sourceDeclarations } = scanned.value;
|
|
9219
|
-
const { paths: assetPaths } = loadAssetConfig(cwd);
|
|
9220
10015
|
const entries = [];
|
|
9221
10016
|
const errors = [];
|
|
9222
10017
|
const declarations = /* @__PURE__ */ new Map();
|
|
@@ -9227,7 +10022,6 @@ async function buildCatalogProjection(roots, options) {
|
|
|
9227
10022
|
path,
|
|
9228
10023
|
cwd,
|
|
9229
10024
|
base,
|
|
9230
|
-
assetPaths,
|
|
9231
10025
|
options.importerPolicy,
|
|
9232
10026
|
options.visibility,
|
|
9233
10027
|
sourceDeclaration,
|
|
@@ -9389,13 +10183,13 @@ function topologyGroups(rows) {
|
|
|
9389
10183
|
}
|
|
9390
10184
|
return groups;
|
|
9391
10185
|
}
|
|
9392
|
-
function revisionDiagnostic(code, expected,
|
|
10186
|
+
function revisionDiagnostic(code, expected, actual, hint, rootId) {
|
|
9393
10187
|
return {
|
|
9394
10188
|
code,
|
|
9395
10189
|
severity: "blocking",
|
|
9396
10190
|
authority: "catalog",
|
|
9397
10191
|
expected,
|
|
9398
|
-
actual
|
|
10192
|
+
actual,
|
|
9399
10193
|
hint,
|
|
9400
10194
|
...rootId === void 0 ? {} : { subject: { type: "package", id: rootId } }
|
|
9401
10195
|
};
|
|
@@ -9521,7 +10315,9 @@ function textureValues(values, textureFields) {
|
|
|
9521
10315
|
}
|
|
9522
10316
|
function collectMaterialCookRefs(material) {
|
|
9523
10317
|
const textureFields = material.parameters === void 0 ? new Set(MATERIAL_TEXTURE_SLOTS) : new Set(
|
|
9524
|
-
material.parameters.filter(
|
|
10318
|
+
material.parameters.filter(
|
|
10319
|
+
(parameter) => parameter.type === "texture" || parameter.type === "texture_cube"
|
|
10320
|
+
).map((parameter) => parameter.name)
|
|
9525
10321
|
);
|
|
9526
10322
|
const textures = textureValues(material.values, textureFields);
|
|
9527
10323
|
return {
|
|
@@ -9555,20 +10351,20 @@ function jsonValue(value) {
|
|
|
9555
10351
|
}
|
|
9556
10352
|
return value;
|
|
9557
10353
|
}
|
|
9558
|
-
function serializeCookedMaterialRecord(
|
|
9559
|
-
return JSON.stringify(jsonValue(
|
|
10354
|
+
function serializeCookedMaterialRecord(record2) {
|
|
10355
|
+
return JSON.stringify(jsonValue(record2));
|
|
9560
10356
|
}
|
|
9561
10357
|
function serializeMaterialCookReceipt(receipt) {
|
|
9562
10358
|
return JSON.stringify(jsonValue({ ...receipt, sourceClosure: unique(receipt.sourceClosure) }));
|
|
9563
10359
|
}
|
|
9564
|
-
function
|
|
10360
|
+
function invalid(field, actual) {
|
|
9565
10361
|
return err({
|
|
9566
10362
|
code: "material-cook-record-invalid",
|
|
9567
10363
|
expected: "a complete material-cook/3 record with layered identity and provenance",
|
|
9568
10364
|
hint: "re-cook the material and publish its record, artifact, references, and receipt together",
|
|
9569
10365
|
detail: {
|
|
9570
10366
|
field,
|
|
9571
|
-
...
|
|
10367
|
+
...actual === void 0 ? {} : { actual },
|
|
9572
10368
|
action: "inspect the named field and recook the material generation"
|
|
9573
10369
|
}
|
|
9574
10370
|
});
|
|
@@ -9589,25 +10385,25 @@ function isGeneration(value) {
|
|
|
9589
10385
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= 1;
|
|
9590
10386
|
}
|
|
9591
10387
|
function validateIdentity(value) {
|
|
9592
|
-
if (value === null || typeof value !== "object") return
|
|
10388
|
+
if (value === null || typeof value !== "object") return invalid("receipt.identity", value);
|
|
9593
10389
|
const candidate = value;
|
|
9594
10390
|
for (const field of IDENTITY_FIELDS) {
|
|
9595
10391
|
if (typeof candidate[field] !== "string" || candidate[field].length === 0) {
|
|
9596
|
-
return
|
|
10392
|
+
return invalid(`receipt.identity.${field}`, candidate[field]);
|
|
9597
10393
|
}
|
|
9598
10394
|
}
|
|
9599
10395
|
if (candidate.wasm === null || typeof candidate.wasm !== "object") {
|
|
9600
|
-
return
|
|
10396
|
+
return invalid("receipt.identity.wasm", candidate.wasm);
|
|
9601
10397
|
}
|
|
9602
10398
|
const wasm = candidate.wasm;
|
|
9603
10399
|
for (const field of ["sourceContentKey", "artifactSha256", "glueSha256"]) {
|
|
9604
10400
|
if (typeof wasm[field] !== "string" || wasm[field].length === 0) {
|
|
9605
|
-
return
|
|
10401
|
+
return invalid(`receipt.identity.wasm.${field}`, wasm[field]);
|
|
9606
10402
|
}
|
|
9607
10403
|
}
|
|
9608
10404
|
for (const field of ["valueGeneration", "dependencyGeneration", "cookGeneration"]) {
|
|
9609
10405
|
if (!isGeneration(candidate[field]))
|
|
9610
|
-
return
|
|
10406
|
+
return invalid(`receipt.identity.${field}`, candidate[field]);
|
|
9611
10407
|
}
|
|
9612
10408
|
return ok({
|
|
9613
10409
|
...candidate,
|
|
@@ -9615,38 +10411,38 @@ function validateIdentity(value) {
|
|
|
9615
10411
|
});
|
|
9616
10412
|
}
|
|
9617
10413
|
function validateMaterialCookReceipt(value, expected = {}) {
|
|
9618
|
-
if (value === null || typeof value !== "object") return
|
|
10414
|
+
if (value === null || typeof value !== "object") return invalid("receipt");
|
|
9619
10415
|
const candidate = value;
|
|
9620
10416
|
if (candidate.schemaVersion !== "material-cook/3")
|
|
9621
|
-
return
|
|
10417
|
+
return invalid("receipt.schemaVersion", candidate.schemaVersion);
|
|
9622
10418
|
const identityResult = validateIdentity(candidate.identity);
|
|
9623
10419
|
if (!identityResult.ok) return identityResult;
|
|
9624
10420
|
const identity = identityResult.value;
|
|
9625
10421
|
if (candidate.derivedInterface === null || typeof candidate.derivedInterface !== "object") {
|
|
9626
|
-
return
|
|
10422
|
+
return invalid("receipt.derivedInterface", candidate.derivedInterface);
|
|
9627
10423
|
}
|
|
9628
10424
|
const derivedInterface = candidate.derivedInterface;
|
|
9629
10425
|
if (derivedInterface.layoutIdentity !== identity.layoutIdentity) {
|
|
9630
|
-
return
|
|
10426
|
+
return invalid("receipt.derivedInterface.layoutIdentity", derivedInterface.layoutIdentity);
|
|
9631
10427
|
}
|
|
9632
10428
|
for (const field of ["sourceClosure", "profile", "compilerVersion"]) {
|
|
9633
10429
|
const fieldValue = candidate[field];
|
|
9634
10430
|
if (field === "sourceClosure" && !Array.isArray(fieldValue) || field !== "sourceClosure" && typeof fieldValue !== "string") {
|
|
9635
|
-
return
|
|
10431
|
+
return invalid(`receipt.${field}`, fieldValue);
|
|
9636
10432
|
}
|
|
9637
10433
|
}
|
|
9638
10434
|
const sourceClosure = candidate.sourceClosure;
|
|
9639
10435
|
if (Array.isArray(sourceClosure) && sourceClosure.some((path) => typeof path !== "string")) {
|
|
9640
|
-
return
|
|
10436
|
+
return invalid("receipt.sourceClosure", sourceClosure);
|
|
9641
10437
|
}
|
|
9642
10438
|
if (expected.layoutIdentity !== void 0 && identity.layoutIdentity !== expected.layoutIdentity) {
|
|
9643
|
-
return
|
|
10439
|
+
return invalid("receipt.identity.layoutIdentity", identity.layoutIdentity);
|
|
9644
10440
|
}
|
|
9645
10441
|
if (expected.artifactDigest !== void 0 && identity.artifactDigest !== expected.artifactDigest) {
|
|
9646
|
-
return
|
|
10442
|
+
return invalid("receipt.identity.artifactDigest", identity.artifactDigest);
|
|
9647
10443
|
}
|
|
9648
10444
|
if (expected.inputDigest !== void 0 && identity.cookIdentity !== expected.inputDigest) {
|
|
9649
|
-
return
|
|
10445
|
+
return invalid("receipt.identity.cookIdentity", identity.cookIdentity);
|
|
9650
10446
|
}
|
|
9651
10447
|
return ok({
|
|
9652
10448
|
schemaVersion: "material-cook/3",
|
|
@@ -9658,49 +10454,49 @@ function validateMaterialCookReceipt(value, expected = {}) {
|
|
|
9658
10454
|
});
|
|
9659
10455
|
}
|
|
9660
10456
|
function validateCookedMaterialRecord(value) {
|
|
9661
|
-
if (value === null || typeof value !== "object") return
|
|
10457
|
+
if (value === null || typeof value !== "object") return invalid("record");
|
|
9662
10458
|
const candidate = value;
|
|
9663
10459
|
if (candidate.schemaVersion !== "material-cook/3")
|
|
9664
|
-
return
|
|
9665
|
-
if (typeof candidate.guid !== "string" || !candidate.guid) return
|
|
10460
|
+
return invalid("schemaVersion", candidate.schemaVersion);
|
|
10461
|
+
if (typeof candidate.guid !== "string" || !candidate.guid) return invalid("guid");
|
|
9666
10462
|
if (candidate.materialGuid !== void 0 && typeof candidate.materialGuid !== "string")
|
|
9667
|
-
return
|
|
10463
|
+
return invalid("materialGuid");
|
|
9668
10464
|
if (candidate.publicationGeneration !== void 0 && !isGeneration(candidate.publicationGeneration))
|
|
9669
|
-
return
|
|
10465
|
+
return invalid("publicationGeneration", candidate.publicationGeneration);
|
|
9670
10466
|
if (candidate.specializationKey !== void 0 && typeof candidate.specializationKey !== "string")
|
|
9671
|
-
return
|
|
10467
|
+
return invalid("specializationKey");
|
|
9672
10468
|
if (candidate.artifactDigest !== void 0 && typeof candidate.artifactDigest !== "string")
|
|
9673
|
-
return
|
|
10469
|
+
return invalid("artifactDigest");
|
|
9674
10470
|
if (candidate.sourceClosure !== void 0 && (!Array.isArray(candidate.sourceClosure) || candidate.sourceClosure.some((path) => typeof path !== "string")))
|
|
9675
|
-
return
|
|
10471
|
+
return invalid("sourceClosure");
|
|
9676
10472
|
if (candidate.parameterContract !== void 0) {
|
|
9677
10473
|
if (candidate.parameterContract === null || typeof candidate.parameterContract !== "object")
|
|
9678
|
-
return
|
|
10474
|
+
return invalid("parameterContract");
|
|
9679
10475
|
const parameterContract = candidate.parameterContract;
|
|
9680
10476
|
if (!Array.isArray(parameterContract.parameters))
|
|
9681
|
-
return
|
|
10477
|
+
return invalid("parameterContract.parameters");
|
|
9682
10478
|
if (parameterContract.values === null || typeof parameterContract.values !== "object" || Array.isArray(parameterContract.values))
|
|
9683
|
-
return
|
|
10479
|
+
return invalid("parameterContract.values");
|
|
9684
10480
|
}
|
|
9685
10481
|
if (candidate.resolved === null || typeof candidate.resolved !== "object")
|
|
9686
|
-
return
|
|
9687
|
-
if (candidate.refs === null || typeof candidate.refs !== "object") return
|
|
10482
|
+
return invalid("resolved");
|
|
10483
|
+
if (candidate.refs === null || typeof candidate.refs !== "object") return invalid("refs");
|
|
9688
10484
|
if (candidate.artifact === null || typeof candidate.artifact !== "object")
|
|
9689
|
-
return
|
|
10485
|
+
return invalid("artifact");
|
|
9690
10486
|
if (candidate.receipt === null || typeof candidate.receipt !== "object")
|
|
9691
|
-
return
|
|
10487
|
+
return invalid("receipt");
|
|
9692
10488
|
const artifact = candidate.artifact;
|
|
9693
10489
|
if (typeof artifact.digest !== "string" || !Array.isArray(artifact.bytes) && !ArrayBuffer.isView(artifact.bytes)) {
|
|
9694
|
-
return
|
|
10490
|
+
return invalid("artifact");
|
|
9695
10491
|
}
|
|
9696
10492
|
const receiptResult = validateMaterialCookReceipt(candidate.receipt, {
|
|
9697
10493
|
artifactDigest: artifact.digest
|
|
9698
10494
|
});
|
|
9699
10495
|
if (!receiptResult.ok) return receiptResult;
|
|
9700
10496
|
if (candidate.artifactDigest !== void 0 && candidate.artifactDigest !== artifact.digest)
|
|
9701
|
-
return
|
|
10497
|
+
return invalid("artifactDigest", candidate.artifactDigest);
|
|
9702
10498
|
if (candidate.publicationGeneration !== void 0 && receiptResult.value.identity.cookGeneration !== candidate.publicationGeneration)
|
|
9703
|
-
return
|
|
10499
|
+
return invalid("receipt.identity.cookGeneration", receiptResult.value.identity.cookGeneration);
|
|
9704
10500
|
const normalized = {
|
|
9705
10501
|
...candidate,
|
|
9706
10502
|
artifact: {
|
|
@@ -9711,13 +10507,13 @@ function validateCookedMaterialRecord(value) {
|
|
|
9711
10507
|
};
|
|
9712
10508
|
return ok(normalized);
|
|
9713
10509
|
}
|
|
9714
|
-
function projectCookedMaterialRecord(
|
|
10510
|
+
function projectCookedMaterialRecord(record2) {
|
|
9715
10511
|
return {
|
|
9716
|
-
resolved:
|
|
9717
|
-
refs:
|
|
9718
|
-
artifact:
|
|
9719
|
-
receipt:
|
|
9720
|
-
schemaVersion:
|
|
10512
|
+
resolved: record2.resolved,
|
|
10513
|
+
refs: record2.refs,
|
|
10514
|
+
artifact: record2.artifact,
|
|
10515
|
+
receipt: record2.receipt,
|
|
10516
|
+
schemaVersion: record2.schemaVersion
|
|
9721
10517
|
};
|
|
9722
10518
|
}
|
|
9723
10519
|
function packageEvidence(input) {
|
|
@@ -9760,12 +10556,150 @@ function packageVerification(input) {
|
|
|
9760
10556
|
};
|
|
9761
10557
|
}
|
|
9762
10558
|
|
|
10559
|
+
// src/inventory/binding.ts
|
|
10560
|
+
function projectAssetRefs(inventory) {
|
|
10561
|
+
return inventory.declarations.map(
|
|
10562
|
+
(row) => ({
|
|
10563
|
+
guid: row.guid,
|
|
10564
|
+
sourceKey: row.sourceKey,
|
|
10565
|
+
kind: row.kind
|
|
10566
|
+
})
|
|
10567
|
+
);
|
|
10568
|
+
}
|
|
10569
|
+
function projectSceneEntityRefs(inventory) {
|
|
10570
|
+
return inventory.declarations.flatMap(
|
|
10571
|
+
(row) => row.sceneBindings === void 0 ? [] : row.sceneBindings.map((bindingKey) => ({
|
|
10572
|
+
sceneSourceKey: row.sourceKey,
|
|
10573
|
+
bindingKey
|
|
10574
|
+
}))
|
|
10575
|
+
);
|
|
10576
|
+
}
|
|
10577
|
+
function failure2(code, expected, hint, detail) {
|
|
10578
|
+
return err({ code, expected, hint, detail });
|
|
10579
|
+
}
|
|
10580
|
+
function validateAuthorInventory(value) {
|
|
10581
|
+
if (typeof value !== "object" || value === null || !Array.isArray(value.declarations)) {
|
|
10582
|
+
return failure2(
|
|
10583
|
+
"inventory-source-key-missing",
|
|
10584
|
+
"an author inventory with declaration rows",
|
|
10585
|
+
"declare each author asset in the source inventory",
|
|
10586
|
+
{}
|
|
10587
|
+
);
|
|
10588
|
+
}
|
|
10589
|
+
const guids = /* @__PURE__ */ new Set();
|
|
10590
|
+
const sourceKeys = /* @__PURE__ */ new Set();
|
|
10591
|
+
const declarations = [];
|
|
10592
|
+
const rows = value.declarations;
|
|
10593
|
+
for (const raw of rows) {
|
|
10594
|
+
if (typeof raw !== "object" || raw === null) {
|
|
10595
|
+
return failure2(
|
|
10596
|
+
"inventory-source-key-missing",
|
|
10597
|
+
"each declaration has a non-empty sourceKey",
|
|
10598
|
+
"add sourceKey to the author declaration before projection",
|
|
10599
|
+
{}
|
|
10600
|
+
);
|
|
10601
|
+
}
|
|
10602
|
+
const row = raw;
|
|
10603
|
+
const guid = typeof row.guid === "string" ? row.guid : void 0;
|
|
10604
|
+
const sourceKey2 = typeof row.sourceKey === "string" ? row.sourceKey : void 0;
|
|
10605
|
+
if (guid === void 0 || sourceKey2 === void 0 || sourceKey2.trim().length === 0 || sourceKey2 !== sourceKey2.trim()) {
|
|
10606
|
+
return failure2(
|
|
10607
|
+
"inventory-source-key-missing",
|
|
10608
|
+
"each declaration has a non-empty sourceKey",
|
|
10609
|
+
"add sourceKey to the author declaration before projection",
|
|
10610
|
+
{
|
|
10611
|
+
...guid === void 0 ? {} : { guid },
|
|
10612
|
+
...sourceKey2 === void 0 ? {} : { sourceKey: sourceKey2 }
|
|
10613
|
+
}
|
|
10614
|
+
);
|
|
10615
|
+
}
|
|
10616
|
+
const normalizedGuid = guid.toLowerCase();
|
|
10617
|
+
if (guids.has(normalizedGuid)) {
|
|
10618
|
+
return failure2(
|
|
10619
|
+
"inventory-guid-duplicate",
|
|
10620
|
+
"every GUID identifies exactly one author declaration",
|
|
10621
|
+
"remove or rename the duplicate GUID before publishing the inventory",
|
|
10622
|
+
{ guid, sourceKey: sourceKey2 }
|
|
10623
|
+
);
|
|
10624
|
+
}
|
|
10625
|
+
if (sourceKeys.has(sourceKey2)) {
|
|
10626
|
+
return failure2(
|
|
10627
|
+
"inventory-source-key-duplicate",
|
|
10628
|
+
"every sourceKey identifies exactly one author declaration",
|
|
10629
|
+
"rename the duplicate semantic sourceKey before publishing the inventory",
|
|
10630
|
+
{ guid, sourceKey: sourceKey2 }
|
|
10631
|
+
);
|
|
10632
|
+
}
|
|
10633
|
+
if (row.kind === "scene") {
|
|
10634
|
+
const payload = row.payload;
|
|
10635
|
+
const payloadRecord = typeof payload === "object" && payload !== null ? payload : void 0;
|
|
10636
|
+
const entities = payloadRecord !== void 0 && Array.isArray(payloadRecord.entities) ? payloadRecord.entities : [];
|
|
10637
|
+
const bindings = /* @__PURE__ */ new Set();
|
|
10638
|
+
for (const entity of entities) {
|
|
10639
|
+
const bindingKey = typeof entity === "object" && entity !== null && typeof entity.bindingKey === "string" ? entity.bindingKey : void 0;
|
|
10640
|
+
if (bindingKey !== void 0 && bindingKey.length === 0) {
|
|
10641
|
+
return failure2(
|
|
10642
|
+
"inventory-scene-binding-missing",
|
|
10643
|
+
"each declared scene bindingKey is non-empty",
|
|
10644
|
+
"remove the empty bindingKey or declare a stable key in the scene producer",
|
|
10645
|
+
{ sourceKey: sourceKey2 }
|
|
10646
|
+
);
|
|
10647
|
+
}
|
|
10648
|
+
if (bindingKey === void 0) continue;
|
|
10649
|
+
if (bindings.has(bindingKey)) {
|
|
10650
|
+
return failure2(
|
|
10651
|
+
"inventory-scene-binding-duplicate",
|
|
10652
|
+
"bindingKey values are unique within one scene",
|
|
10653
|
+
"rename the duplicate bindingKey in the scene producer",
|
|
10654
|
+
{ sourceKey: sourceKey2 }
|
|
10655
|
+
);
|
|
10656
|
+
}
|
|
10657
|
+
bindings.add(bindingKey);
|
|
10658
|
+
}
|
|
10659
|
+
}
|
|
10660
|
+
guids.add(normalizedGuid);
|
|
10661
|
+
sourceKeys.add(sourceKey2);
|
|
10662
|
+
const sceneBindings = row.kind === "scene" && typeof row.payload === "object" && row.payload !== null ? row.payload.entities?.flatMap(
|
|
10663
|
+
(entity) => {
|
|
10664
|
+
if (typeof entity !== "object" || entity === null) return [];
|
|
10665
|
+
const key = entity.bindingKey;
|
|
10666
|
+
return typeof key === "string" && key.length > 0 ? [key] : [];
|
|
10667
|
+
}
|
|
10668
|
+
) : void 0;
|
|
10669
|
+
declarations.push({
|
|
10670
|
+
guid,
|
|
10671
|
+
sourceKey: sourceKey2,
|
|
10672
|
+
kind: typeof row.kind === "string" ? row.kind : "unknown",
|
|
10673
|
+
payload: typeof row.payload === "object" && row.payload !== null ? row.payload : {},
|
|
10674
|
+
refs: Array.isArray(row.refs) ? row.refs.filter((ref) => typeof ref === "string") : [],
|
|
10675
|
+
...sceneBindings === void 0 ? {} : { sceneBindings }
|
|
10676
|
+
});
|
|
10677
|
+
}
|
|
10678
|
+
return ok({ declarations });
|
|
10679
|
+
}
|
|
10680
|
+
|
|
10681
|
+
// src/inventory/sync.ts
|
|
10682
|
+
function inventoryDigest(inventory) {
|
|
10683
|
+
return inventory.declarations.map(
|
|
10684
|
+
(row) => `${row.guid}\0${row.sourceKey}\0${row.kind}\0${row.sceneBindings?.join("\0") ?? ""}`
|
|
10685
|
+
).sort().join("\n");
|
|
10686
|
+
}
|
|
10687
|
+
function syncAuthorInventory(inventory) {
|
|
10688
|
+
return {
|
|
10689
|
+
declarations: inventory.declarations.map((row) => ({
|
|
10690
|
+
...row,
|
|
10691
|
+
refs: [...row.refs],
|
|
10692
|
+
...row.sceneBindings === void 0 ? {} : { sceneBindings: [...row.sceneBindings] }
|
|
10693
|
+
}))
|
|
10694
|
+
};
|
|
10695
|
+
}
|
|
10696
|
+
|
|
9763
10697
|
// src/mesh-bin-contract.ts
|
|
9764
10698
|
var MESH_BIN_VERSION = 4;
|
|
9765
10699
|
var MESH_BIN_PROJECTION_VERSION = 1;
|
|
9766
10700
|
var MESH_BIN_HEADER_V4_BYTES = 80;
|
|
9767
10701
|
var MESH_BIN_DIGEST_BYTES = 32;
|
|
9768
|
-
function
|
|
10702
|
+
function failure3(code, sourceKey2, expected, actual) {
|
|
9769
10703
|
return {
|
|
9770
10704
|
ok: false,
|
|
9771
10705
|
error: {
|
|
@@ -9773,7 +10707,7 @@ function failure(code, sourceKey2, expected, actual2) {
|
|
|
9773
10707
|
subject: "mesh-bin",
|
|
9774
10708
|
sourceKey: sourceKey2,
|
|
9775
10709
|
expected,
|
|
9776
|
-
actual
|
|
10710
|
+
actual,
|
|
9777
10711
|
recovery: "re-cook the source with its Meta sidecar through the build-time importer"
|
|
9778
10712
|
}
|
|
9779
10713
|
};
|
|
@@ -9805,7 +10739,7 @@ function writeMeshBinHeader(header, out) {
|
|
|
9805
10739
|
}
|
|
9806
10740
|
function decodeMeshBinHeader(bytes, sourceKey2 = "<unknown mesh source>") {
|
|
9807
10741
|
if (bytes.byteLength < MESH_BIN_HEADER_V4_BYTES) {
|
|
9808
|
-
return
|
|
10742
|
+
return failure3(
|
|
9809
10743
|
"mesh-bin-header-truncated",
|
|
9810
10744
|
sourceKey2,
|
|
9811
10745
|
`mesh-bin v4 header (${MESH_BIN_HEADER_V4_BYTES} bytes)`,
|
|
@@ -9815,7 +10749,7 @@ function decodeMeshBinHeader(bytes, sourceKey2 = "<unknown mesh source>") {
|
|
|
9815
10749
|
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
9816
10750
|
const version = view.getUint32(0, true);
|
|
9817
10751
|
if (version !== MESH_BIN_VERSION) {
|
|
9818
|
-
return
|
|
10752
|
+
return failure3("mesh-bin-version-unsupported", sourceKey2, "mesh-bin v4", `version ${version}`);
|
|
9819
10753
|
}
|
|
9820
10754
|
const projectionVersion = view.getUint32(4, true);
|
|
9821
10755
|
const mask = view.getUint32(8, true);
|
|
@@ -9828,7 +10762,7 @@ function decodeMeshBinHeader(bytes, sourceKey2 = "<unknown mesh source>") {
|
|
|
9828
10762
|
const jsonBytes = view.getUint32(36, true);
|
|
9829
10763
|
const digest3 = readDigest(bytes.subarray(48, 48 + MESH_BIN_DIGEST_BYTES));
|
|
9830
10764
|
if (projectionVersion !== MESH_BIN_PROJECTION_VERSION || mask === 0 || stride === 0 || !Number.isSafeInteger(vertexCount) || !Number.isSafeInteger(vertexBytes) || !Number.isSafeInteger(indexCount) || !Number.isSafeInteger(indexBytes) || !Number.isSafeInteger(jsonBytes) || indexCount === 0 && indexWidth !== 0 || indexCount > 0 && indexWidth !== 2 && indexWidth !== 4 || indexBytes !== indexCount * indexWidth || vertexBytes !== vertexCount * stride || digest3.length === 0) {
|
|
9831
|
-
return
|
|
10765
|
+
return failure3(
|
|
9832
10766
|
"mesh-bin-header-invalid",
|
|
9833
10767
|
sourceKey2,
|
|
9834
10768
|
"safe v4 projection, stride, cardinality, and payload byte lengths",
|
|
@@ -9852,24 +10786,7 @@ function decodeMeshBinHeader(bytes, sourceKey2 = "<unknown mesh source>") {
|
|
|
9852
10786
|
}
|
|
9853
10787
|
};
|
|
9854
10788
|
}
|
|
9855
|
-
function
|
|
9856
|
-
if (pack.schemaVersion !== "1.0.0" || pack.assets === void 0) return pack;
|
|
9857
|
-
return {
|
|
9858
|
-
...pack,
|
|
9859
|
-
schemaVersion: "2.0.0",
|
|
9860
|
-
assets: pack.assets.map((asset) => {
|
|
9861
|
-
const fontRefs = asset.kind === "font" ? [asset.payload.atlasGuid, asset.payload.samplerGuid].filter(
|
|
9862
|
-
(guid) => typeof guid === "string"
|
|
9863
|
-
) : [];
|
|
9864
|
-
return {
|
|
9865
|
-
...asset,
|
|
9866
|
-
refs: asset.refs ?? fontRefs,
|
|
9867
|
-
artifacts: asset.artifacts ?? {}
|
|
9868
|
-
};
|
|
9869
|
-
})
|
|
9870
|
-
};
|
|
9871
|
-
}
|
|
9872
|
-
function failure2(code, expected, hint, detail) {
|
|
10789
|
+
function failure4(code, expected, hint, detail) {
|
|
9873
10790
|
return { ok: false, error: { code, expected, hint, detail } };
|
|
9874
10791
|
}
|
|
9875
10792
|
function sorted(value) {
|
|
@@ -9968,7 +10885,7 @@ function transportArtifacts(assets, artifactPath) {
|
|
|
9968
10885
|
}
|
|
9969
10886
|
async function finalizePackageProduct(product, policy) {
|
|
9970
10887
|
if (product.sourceRevision.trim().length === 0) {
|
|
9971
|
-
return
|
|
10888
|
+
return failure4(
|
|
9972
10889
|
"missing-source-revision",
|
|
9973
10890
|
"a non-empty source revision",
|
|
9974
10891
|
"rebuild the inventory and provide the producer source revision",
|
|
@@ -9979,7 +10896,7 @@ async function finalizePackageProduct(product, policy) {
|
|
|
9979
10896
|
for (const asset of product.assets) {
|
|
9980
10897
|
const guid = asset.guid.toLowerCase();
|
|
9981
10898
|
if (seen.has(guid)) {
|
|
9982
|
-
return
|
|
10899
|
+
return failure4(
|
|
9983
10900
|
"duplicate-guid",
|
|
9984
10901
|
"one terminal product row per GUID",
|
|
9985
10902
|
"repair the inventory or producer output before finalization",
|
|
@@ -9989,7 +10906,7 @@ async function finalizePackageProduct(product, policy) {
|
|
|
9989
10906
|
seen.add(guid);
|
|
9990
10907
|
for (const [key, artifact] of Object.entries(asset.artifacts)) {
|
|
9991
10908
|
if (!safePath(key) || !(artifact.bytes instanceof Uint8Array)) {
|
|
9992
|
-
return
|
|
10909
|
+
return failure4(
|
|
9993
10910
|
"invalid-artifact",
|
|
9994
10911
|
"asset-local artifact keys and byte bodies",
|
|
9995
10912
|
"repair the producer artifact before finalization",
|
|
@@ -10000,7 +10917,7 @@ async function finalizePackageProduct(product, policy) {
|
|
|
10000
10917
|
}
|
|
10001
10918
|
for (const guid of seen) {
|
|
10002
10919
|
if (!product.receipts.some((receipt) => receipt.guid.toLowerCase() === guid)) {
|
|
10003
|
-
return
|
|
10920
|
+
return failure4(
|
|
10004
10921
|
"missing-receipt",
|
|
10005
10922
|
"one receipt for every terminal product GUID",
|
|
10006
10923
|
"preserve the producer receipt when handing the product to engine-pack",
|
|
@@ -10016,7 +10933,7 @@ async function finalizePackageProduct(product, policy) {
|
|
|
10016
10933
|
for (const [key, artifact] of Object.entries(asset.artifacts)) {
|
|
10017
10934
|
const path = policy.artifactPath(asset.guid, key);
|
|
10018
10935
|
if (!safePath(path)) {
|
|
10019
|
-
return
|
|
10936
|
+
return failure4(
|
|
10020
10937
|
"invalid-artifact",
|
|
10021
10938
|
"package-relative artifact output paths",
|
|
10022
10939
|
"repair the finalizer artifact path policy",
|
|
@@ -10027,7 +10944,7 @@ async function finalizePackageProduct(product, policy) {
|
|
|
10027
10944
|
}
|
|
10028
10945
|
}
|
|
10029
10946
|
if (!safePath(policy.packagePath)) {
|
|
10030
|
-
return
|
|
10947
|
+
return failure4(
|
|
10031
10948
|
"invalid-artifact",
|
|
10032
10949
|
"a package-relative package path",
|
|
10033
10950
|
"repair the finalizer package path policy",
|
|
@@ -10070,6 +10987,7 @@ async function finalizePackageTransportSource(input, policy) {
|
|
|
10070
10987
|
packageUrl: finalized.value.packageUrl,
|
|
10071
10988
|
artifacts: transportArtifacts(product.assets, policy.artifactPath),
|
|
10072
10989
|
digest: finalized.value.digest,
|
|
10990
|
+
receipts: finalized.value.receipts,
|
|
10073
10991
|
sourceRevision,
|
|
10074
10992
|
semantic: JSON.stringify(sorted(finalized.value.pack))
|
|
10075
10993
|
};
|
|
@@ -10092,6 +11010,1601 @@ function revisionStable(value) {
|
|
|
10092
11010
|
function packageTransportRevision(value) {
|
|
10093
11011
|
return createHash("sha256").update(JSON.stringify(revisionStable(value))).digest("hex");
|
|
10094
11012
|
}
|
|
11013
|
+
function isRecord3(value) {
|
|
11014
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
11015
|
+
}
|
|
11016
|
+
function jsonValue2(value) {
|
|
11017
|
+
if (value instanceof Uint8Array) return AssetGuid.format(value);
|
|
11018
|
+
if (Array.isArray(value)) return value.map((item) => jsonValue2(item));
|
|
11019
|
+
if (isRecord3(value)) {
|
|
11020
|
+
return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, jsonValue2(item)]));
|
|
11021
|
+
}
|
|
11022
|
+
return value;
|
|
11023
|
+
}
|
|
11024
|
+
function revisionOf(source) {
|
|
11025
|
+
return `sha256:${createHash("sha256").update(source).digest("hex")}`;
|
|
11026
|
+
}
|
|
11027
|
+
function makeError(code, expected, hint, detail = {}, actual) {
|
|
11028
|
+
return {
|
|
11029
|
+
code,
|
|
11030
|
+
expected,
|
|
11031
|
+
hint,
|
|
11032
|
+
...actual === void 0 ? {} : { actual },
|
|
11033
|
+
detail
|
|
11034
|
+
};
|
|
11035
|
+
}
|
|
11036
|
+
function pathError(code, operation, expected, hint, detail = {}, actual) {
|
|
11037
|
+
return makeError(code, expected, hint, { requestId: operation.requestId, ...detail }, actual);
|
|
11038
|
+
}
|
|
11039
|
+
function confinedPath(gameRoot, candidate, operation) {
|
|
11040
|
+
if (typeof candidate !== "string" || candidate.length === 0 || isAbsolute(candidate)) {
|
|
11041
|
+
return err(
|
|
11042
|
+
pathError(
|
|
11043
|
+
"pack-source-path-invalid",
|
|
11044
|
+
operation,
|
|
11045
|
+
"a non-empty game-root-relative .pack.ts or .pack.json path",
|
|
11046
|
+
"pass a relative source locator inside the selected game root",
|
|
11047
|
+
{ sourcePath: candidate },
|
|
11048
|
+
typeof candidate === "string" ? candidate : void 0
|
|
11049
|
+
)
|
|
11050
|
+
);
|
|
11051
|
+
}
|
|
11052
|
+
const root = resolve(gameRoot);
|
|
11053
|
+
const absolute = resolve(root, candidate);
|
|
11054
|
+
const relativePath = relative(root, absolute).split(sep).join("/");
|
|
11055
|
+
if (relativePath.length === 0 || relativePath === ".." || relativePath.startsWith("../") || !relativePath.endsWith(".pack.ts") && !relativePath.endsWith(".pack.json")) {
|
|
11056
|
+
return err(
|
|
11057
|
+
pathError(
|
|
11058
|
+
"pack-source-path-invalid",
|
|
11059
|
+
operation,
|
|
11060
|
+
"a game-root-relative .pack.ts or .pack.json path",
|
|
11061
|
+
"choose a Pack source path inside the selected game root",
|
|
11062
|
+
{ sourcePath: candidate },
|
|
11063
|
+
candidate
|
|
11064
|
+
)
|
|
11065
|
+
);
|
|
11066
|
+
}
|
|
11067
|
+
return ok({ absolute, relative: relativePath });
|
|
11068
|
+
}
|
|
11069
|
+
async function atomicWrite(path, source) {
|
|
11070
|
+
await mkdir(dirname(path), { recursive: true });
|
|
11071
|
+
const temporary = `${path}.${process.pid}.${Date.now()}.tmp`;
|
|
11072
|
+
try {
|
|
11073
|
+
await writeFile(temporary, source, { encoding: "utf8", flag: "wx" });
|
|
11074
|
+
await rename(temporary, path);
|
|
11075
|
+
} catch (cause) {
|
|
11076
|
+
await rm(temporary, { force: true });
|
|
11077
|
+
throw cause;
|
|
11078
|
+
}
|
|
11079
|
+
}
|
|
11080
|
+
function packageKey(packageId2) {
|
|
11081
|
+
return PackageId.format(packageId2).toLowerCase();
|
|
11082
|
+
}
|
|
11083
|
+
function parsePackageId2(value) {
|
|
11084
|
+
if (typeof value !== "string") return void 0;
|
|
11085
|
+
const parsed = PackageId.parse(value);
|
|
11086
|
+
return parsed.ok ? parsed.value : void 0;
|
|
11087
|
+
}
|
|
11088
|
+
function serializedParameters(definition) {
|
|
11089
|
+
if (!("parameters" in definition)) return void 0;
|
|
11090
|
+
return definition.parameters.map((parameter) => ({
|
|
11091
|
+
name: parameter.name,
|
|
11092
|
+
type: parameter.type,
|
|
11093
|
+
default: jsonValue2(parameter.default),
|
|
11094
|
+
...parameter.minimum === void 0 ? {} : { minimum: parameter.minimum },
|
|
11095
|
+
...parameter.maximum === void 0 ? {} : { maximum: parameter.maximum },
|
|
11096
|
+
...parameter.values === void 0 ? {} : { values: parameter.values },
|
|
11097
|
+
...parameter.kind === void 0 ? {} : { kind: parameter.kind }
|
|
11098
|
+
}));
|
|
11099
|
+
}
|
|
11100
|
+
function sourceResult(subject, operation) {
|
|
11101
|
+
const base = {
|
|
11102
|
+
operation: operation.operation,
|
|
11103
|
+
requestId: operation.requestId,
|
|
11104
|
+
sourcePath: subject.relativePath,
|
|
11105
|
+
packageId: PackageId.format(subject.packageId),
|
|
11106
|
+
format: subject.format === "source" ? "pack.ts" : subject.format
|
|
11107
|
+
};
|
|
11108
|
+
if (subject.format === "source") {
|
|
11109
|
+
const parameters = serializedParameters(subject.definition);
|
|
11110
|
+
return {
|
|
11111
|
+
...base,
|
|
11112
|
+
...parameters === void 0 ? {} : { parameters },
|
|
11113
|
+
...parameters === void 0 ? {} : {
|
|
11114
|
+
capabilities: [
|
|
11115
|
+
"asset-source.create-instance",
|
|
11116
|
+
"asset-source.rebuild",
|
|
11117
|
+
"asset-source.cold-cook"
|
|
11118
|
+
]
|
|
11119
|
+
}
|
|
11120
|
+
};
|
|
11121
|
+
}
|
|
11122
|
+
if (subject.format === "instance") {
|
|
11123
|
+
return {
|
|
11124
|
+
...base,
|
|
11125
|
+
parentPackageId: PackageId.format(subject.parent),
|
|
11126
|
+
values: jsonValue2(subject.values)
|
|
11127
|
+
};
|
|
11128
|
+
}
|
|
11129
|
+
return {
|
|
11130
|
+
...base,
|
|
11131
|
+
assets: subject.assets.map((asset) => ({
|
|
11132
|
+
sourceKey: asset.sourceKey,
|
|
11133
|
+
guid: asset.guid,
|
|
11134
|
+
kind: asset.kind,
|
|
11135
|
+
...asset.name === void 0 ? {} : { name: asset.name },
|
|
11136
|
+
refs: asset.refs
|
|
11137
|
+
}))
|
|
11138
|
+
};
|
|
11139
|
+
}
|
|
11140
|
+
function scanFailure(operation, cause) {
|
|
11141
|
+
const value = cause !== null && typeof cause === "object" ? cause : {};
|
|
11142
|
+
const detail = value.detail !== null && typeof value.detail === "object" ? value.detail : {};
|
|
11143
|
+
const reason = isRecord3(detail) && typeof detail.reason === "string" ? detail.reason : void 0;
|
|
11144
|
+
const code = reason === "pack-parent-not-found" || reason === "pack-parent-cycle" || reason === "pack-parent-not-parameterized" ? reason : value.code === "pack-guid-collision" ? "pack-guid-collision" : "pack-parameter-invalid";
|
|
11145
|
+
return makeError(
|
|
11146
|
+
code,
|
|
11147
|
+
typeof value.expected === "string" ? value.expected : "a valid Pack Source Index",
|
|
11148
|
+
typeof value.hint === "string" ? value.hint : "repair the first source or package diagnostic, then retry",
|
|
11149
|
+
{ requestId: operation.requestId, cause: value.detail ?? String(cause) }
|
|
11150
|
+
);
|
|
11151
|
+
}
|
|
11152
|
+
function scanRoots(options) {
|
|
11153
|
+
return options.scanRoots === void 0 || options.scanRoots.length === 0 ? [resolve(options.gameRoot)] : options.scanRoots.map((root) => resolve(options.gameRoot, root));
|
|
11154
|
+
}
|
|
11155
|
+
async function readMaterialized(options, operation) {
|
|
11156
|
+
let rawRows;
|
|
11157
|
+
try {
|
|
11158
|
+
rawRows = await options.materialized?.() ?? [];
|
|
11159
|
+
} catch (cause) {
|
|
11160
|
+
return err(
|
|
11161
|
+
makeError(
|
|
11162
|
+
"pack-parameter-invalid",
|
|
11163
|
+
"the materialized projection callback to return current-generation rows",
|
|
11164
|
+
"repair the build-owner projection callback, then retry the Pack operation",
|
|
11165
|
+
{
|
|
11166
|
+
requestId: operation.requestId,
|
|
11167
|
+
cause: cause instanceof Error ? cause.message : String(cause)
|
|
11168
|
+
}
|
|
11169
|
+
)
|
|
11170
|
+
);
|
|
11171
|
+
}
|
|
11172
|
+
if (!Array.isArray(rawRows)) {
|
|
11173
|
+
return err(
|
|
11174
|
+
makeError(
|
|
11175
|
+
"pack-parameter-invalid",
|
|
11176
|
+
"the materialized projection callback to return an array",
|
|
11177
|
+
"repair the build-owner projection callback, then retry the Pack operation",
|
|
11178
|
+
{ requestId: operation.requestId, actual: typeof rawRows }
|
|
11179
|
+
)
|
|
11180
|
+
);
|
|
11181
|
+
}
|
|
11182
|
+
const materialized = [];
|
|
11183
|
+
const pairOwners = /* @__PURE__ */ new Map();
|
|
11184
|
+
const guidOwners = /* @__PURE__ */ new Map();
|
|
11185
|
+
for (const rawRow of rawRows) {
|
|
11186
|
+
if (!isRecord3(rawRow)) {
|
|
11187
|
+
return err(
|
|
11188
|
+
makeError(
|
|
11189
|
+
"pack-parameter-invalid",
|
|
11190
|
+
"materialized rows to be objects",
|
|
11191
|
+
"repair the current generation projection before querying Pack authoring",
|
|
11192
|
+
{ requestId: operation.requestId, actual: typeof rawRow }
|
|
11193
|
+
)
|
|
11194
|
+
);
|
|
11195
|
+
}
|
|
11196
|
+
const row = rawRow;
|
|
11197
|
+
const parsedPackageId = parsePackageId2(row.packageId);
|
|
11198
|
+
if (parsedPackageId === void 0) {
|
|
11199
|
+
return err(
|
|
11200
|
+
makeError(
|
|
11201
|
+
"pack-package-id-invalid",
|
|
11202
|
+
"materialized rows to contain a valid UUID packageId",
|
|
11203
|
+
"repair the current generation projection before querying Pack authoring",
|
|
11204
|
+
{ requestId: operation.requestId, packageId: row.packageId, sourceKey: row.sourceKey }
|
|
11205
|
+
)
|
|
11206
|
+
);
|
|
11207
|
+
}
|
|
11208
|
+
if (!isValidPackSourceKey(row.sourceKey)) {
|
|
11209
|
+
return err(
|
|
11210
|
+
makeError(
|
|
11211
|
+
"pack-source-key-invalid",
|
|
11212
|
+
"materialized rows to contain a valid sourceKey",
|
|
11213
|
+
"repair the current generation projection before querying Pack authoring",
|
|
11214
|
+
{ requestId: operation.requestId, packageId: row.packageId, sourceKey: row.sourceKey }
|
|
11215
|
+
)
|
|
11216
|
+
);
|
|
11217
|
+
}
|
|
11218
|
+
if (typeof row.guid !== "string" || !isValidAssetGuidString(row.guid) || typeof row.kind !== "string" || row.kind.length === 0) {
|
|
11219
|
+
return err(
|
|
11220
|
+
makeError(
|
|
11221
|
+
"pack-parameter-invalid",
|
|
11222
|
+
"materialized rows to contain a valid GUID and non-empty kind",
|
|
11223
|
+
"repair the current generation projection before querying Pack authoring",
|
|
11224
|
+
{ requestId: operation.requestId, packageId: row.packageId, sourceKey: row.sourceKey }
|
|
11225
|
+
)
|
|
11226
|
+
);
|
|
11227
|
+
}
|
|
11228
|
+
if (row.refs !== void 0 && (!Array.isArray(row.refs) || row.refs.some((ref) => typeof ref !== "string" || !isValidAssetGuidString(ref)))) {
|
|
11229
|
+
return err(
|
|
11230
|
+
makeError(
|
|
11231
|
+
"pack-parameter-invalid",
|
|
11232
|
+
"materialized refs to contain UUID AssetGuid strings when present",
|
|
11233
|
+
"repair the current generation projection before querying Pack authoring",
|
|
11234
|
+
{ requestId: operation.requestId, packageId: row.packageId, sourceKey: row.sourceKey }
|
|
11235
|
+
)
|
|
11236
|
+
);
|
|
11237
|
+
}
|
|
11238
|
+
if (row.sourcePath !== void 0 && typeof row.sourcePath !== "string") {
|
|
11239
|
+
return err(
|
|
11240
|
+
makeError(
|
|
11241
|
+
"pack-parameter-invalid",
|
|
11242
|
+
"materialized sourcePath to be a string when present",
|
|
11243
|
+
"repair the current generation projection before querying Pack authoring",
|
|
11244
|
+
{ requestId: operation.requestId, sourcePath: row.sourcePath }
|
|
11245
|
+
)
|
|
11246
|
+
);
|
|
11247
|
+
}
|
|
11248
|
+
const packageId2 = PackageId.format(parsedPackageId).toLowerCase();
|
|
11249
|
+
const expectedGuid = AssetGuid.format(
|
|
11250
|
+
AssetGuid.derive(parsedPackageId, row.sourceKey)
|
|
11251
|
+
).toLowerCase();
|
|
11252
|
+
const guid = row.guid.toLowerCase();
|
|
11253
|
+
if (guid !== expectedGuid) {
|
|
11254
|
+
return err(
|
|
11255
|
+
makeError(
|
|
11256
|
+
"pack-guid-collision",
|
|
11257
|
+
"materialized GUID to equal UUIDv5(packageId, sourceKey)",
|
|
11258
|
+
"rebuild the current generation from the stable packageId and sourceKey pair",
|
|
11259
|
+
{
|
|
11260
|
+
requestId: operation.requestId,
|
|
11261
|
+
packageId: packageId2,
|
|
11262
|
+
sourceKey: row.sourceKey,
|
|
11263
|
+
expectedGuid,
|
|
11264
|
+
observedGuid: row.guid
|
|
11265
|
+
}
|
|
11266
|
+
)
|
|
11267
|
+
);
|
|
11268
|
+
}
|
|
11269
|
+
const pair = `${packageId2}/${row.sourceKey}`;
|
|
11270
|
+
const pairOwner = pairOwners.get(pair);
|
|
11271
|
+
if (pairOwner !== void 0) {
|
|
11272
|
+
return err(
|
|
11273
|
+
makeError(
|
|
11274
|
+
"pack-guid-collision",
|
|
11275
|
+
"one materialized row per packageId/sourceKey pair",
|
|
11276
|
+
"remove the stale duplicate row from the current generation projection",
|
|
11277
|
+
{ requestId: operation.requestId, pair, paths: [pairOwner, row.sourcePath] }
|
|
11278
|
+
)
|
|
11279
|
+
);
|
|
11280
|
+
}
|
|
11281
|
+
pairOwners.set(pair, row.sourcePath ?? pair);
|
|
11282
|
+
const guidOwner = guidOwners.get(guid);
|
|
11283
|
+
if (guidOwner !== void 0) {
|
|
11284
|
+
return err(
|
|
11285
|
+
makeError(
|
|
11286
|
+
"pack-guid-collision",
|
|
11287
|
+
"one materialized owner per derived AssetGuid",
|
|
11288
|
+
"repair the current generation projection so each derived GUID has one owner",
|
|
11289
|
+
{ requestId: operation.requestId, guid, paths: [guidOwner, row.sourcePath] }
|
|
11290
|
+
)
|
|
11291
|
+
);
|
|
11292
|
+
}
|
|
11293
|
+
guidOwners.set(guid, row.sourcePath ?? pair);
|
|
11294
|
+
materialized.push({
|
|
11295
|
+
packageId: packageId2,
|
|
11296
|
+
sourceKey: row.sourceKey,
|
|
11297
|
+
guid,
|
|
11298
|
+
kind: row.kind,
|
|
11299
|
+
...row.sourcePath === void 0 ? {} : { sourcePath: row.sourcePath },
|
|
11300
|
+
...row.refs === void 0 ? {} : { refs: Object.freeze([...row.refs]) },
|
|
11301
|
+
ready: row.ready === true && row.artifactsReady !== false
|
|
11302
|
+
});
|
|
11303
|
+
}
|
|
11304
|
+
materialized.sort(
|
|
11305
|
+
(left, right) => `${left.packageId}/${left.sourceKey}`.localeCompare(`${right.packageId}/${right.sourceKey}`)
|
|
11306
|
+
);
|
|
11307
|
+
return ok(materialized);
|
|
11308
|
+
}
|
|
11309
|
+
async function createSnapshot(options, operation) {
|
|
11310
|
+
const scanned = options.inventory === void 0 ? await scanInventory(scanRoots(options)) : await options.inventory();
|
|
11311
|
+
if (!scanned.ok) return err(scanFailure(operation, scanned.error));
|
|
11312
|
+
const subjects = /* @__PURE__ */ new Map();
|
|
11313
|
+
const directAssets = [];
|
|
11314
|
+
for (const [sourcePath, declaration] of scanned.value.declarations) {
|
|
11315
|
+
const relativePath = relative(resolve(options.gameRoot), sourcePath).split(sep).join("/");
|
|
11316
|
+
if (declaration.format === "pack.ts-parameterized") {
|
|
11317
|
+
subjects.set(packageKey(declaration.definition.packageId), {
|
|
11318
|
+
format: "source",
|
|
11319
|
+
packageId: declaration.definition.packageId,
|
|
11320
|
+
sourcePath,
|
|
11321
|
+
relativePath,
|
|
11322
|
+
definition: declaration.definition
|
|
11323
|
+
});
|
|
11324
|
+
continue;
|
|
11325
|
+
}
|
|
11326
|
+
if (declaration.format !== "pack.json" || declaration.value.schemaVersion !== "3.0.0") continue;
|
|
11327
|
+
const parsed = parseParameterizedPackJson(declaration.value);
|
|
11328
|
+
if (!parsed.ok) return err(parsed.error);
|
|
11329
|
+
if (parsed.value.format === "direct") {
|
|
11330
|
+
const projected = projectDirectPackJson(parsed.value);
|
|
11331
|
+
if (!projected.ok) return err(projected.error);
|
|
11332
|
+
const subject = {
|
|
11333
|
+
format: "direct",
|
|
11334
|
+
packageId: parsed.value.packageId,
|
|
11335
|
+
sourcePath,
|
|
11336
|
+
relativePath,
|
|
11337
|
+
assets: projected.value.assets
|
|
11338
|
+
};
|
|
11339
|
+
subjects.set(packageKey(subject.packageId), subject);
|
|
11340
|
+
directAssets.push(
|
|
11341
|
+
...projected.value.assets.map((asset) => ({
|
|
11342
|
+
packageId: projected.value.packageId.toLowerCase(),
|
|
11343
|
+
sourceKey: asset.sourceKey,
|
|
11344
|
+
guid: asset.guid.toLowerCase(),
|
|
11345
|
+
kind: asset.kind,
|
|
11346
|
+
sourcePath: relativePath,
|
|
11347
|
+
...asset.name === void 0 ? {} : { name: asset.name },
|
|
11348
|
+
refs: asset.refs
|
|
11349
|
+
}))
|
|
11350
|
+
);
|
|
11351
|
+
} else {
|
|
11352
|
+
subjects.set(packageKey(parsed.value.packageId), {
|
|
11353
|
+
format: "instance",
|
|
11354
|
+
packageId: parsed.value.packageId,
|
|
11355
|
+
parent: parsed.value.parent,
|
|
11356
|
+
values: parsed.value.values,
|
|
11357
|
+
sourcePath,
|
|
11358
|
+
relativePath
|
|
11359
|
+
});
|
|
11360
|
+
}
|
|
11361
|
+
}
|
|
11362
|
+
const materializedResult = await readMaterialized(options, operation);
|
|
11363
|
+
if (!materializedResult.ok) return materializedResult;
|
|
11364
|
+
const materialized = materializedResult.value;
|
|
11365
|
+
const guidOwners = /* @__PURE__ */ new Map();
|
|
11366
|
+
const directPairs = /* @__PURE__ */ new Set();
|
|
11367
|
+
for (const entry of scanned.value.inventory) {
|
|
11368
|
+
const declaration = scanned.value.declarations.get(entry.sourcePath);
|
|
11369
|
+
if (declaration?.format === "pack.json" && declaration.value.schemaVersion === "3.0.0") {
|
|
11370
|
+
continue;
|
|
11371
|
+
}
|
|
11372
|
+
guidOwners.set(entry.guid.toLowerCase(), entry.sourcePath);
|
|
11373
|
+
}
|
|
11374
|
+
for (const asset of directAssets) {
|
|
11375
|
+
directPairs.add(`${asset.packageId}/${asset.sourceKey}`);
|
|
11376
|
+
const existing = guidOwners.get(asset.guid);
|
|
11377
|
+
if (existing !== void 0) {
|
|
11378
|
+
return err(
|
|
11379
|
+
makeError(
|
|
11380
|
+
"pack-guid-collision",
|
|
11381
|
+
"one current-generation owner per AssetGuid",
|
|
11382
|
+
"repair the direct Pack or external source projection before querying Pack authoring",
|
|
11383
|
+
{
|
|
11384
|
+
requestId: operation.requestId,
|
|
11385
|
+
guid: asset.guid,
|
|
11386
|
+
paths: [existing, asset.sourcePath]
|
|
11387
|
+
}
|
|
11388
|
+
)
|
|
11389
|
+
);
|
|
11390
|
+
}
|
|
11391
|
+
guidOwners.set(asset.guid, asset.sourcePath ?? asset.packageId);
|
|
11392
|
+
}
|
|
11393
|
+
for (const asset of materialized) {
|
|
11394
|
+
const existing = guidOwners.get(asset.guid);
|
|
11395
|
+
const pair = `${asset.packageId}/${asset.sourceKey}`;
|
|
11396
|
+
if (existing !== void 0 && !directPairs.has(pair)) {
|
|
11397
|
+
return err(
|
|
11398
|
+
makeError(
|
|
11399
|
+
"pack-guid-collision",
|
|
11400
|
+
"one current-generation owner per AssetGuid",
|
|
11401
|
+
"remove the stale materialized row or repair the direct/source owner before querying Pack authoring",
|
|
11402
|
+
{
|
|
11403
|
+
requestId: operation.requestId,
|
|
11404
|
+
guid: asset.guid,
|
|
11405
|
+
paths: [existing, asset.sourcePath]
|
|
11406
|
+
}
|
|
11407
|
+
)
|
|
11408
|
+
);
|
|
11409
|
+
}
|
|
11410
|
+
guidOwners.set(asset.guid, asset.sourcePath ?? asset.packageId);
|
|
11411
|
+
}
|
|
11412
|
+
const knownGuids = /* @__PURE__ */ new Set([
|
|
11413
|
+
...scanned.value.inventory.map((entry) => entry.guid.toLowerCase()),
|
|
11414
|
+
...directAssets.map((asset) => asset.guid),
|
|
11415
|
+
...materialized.map((asset) => asset.guid)
|
|
11416
|
+
]);
|
|
11417
|
+
return ok({ inventory: scanned.value, subjects, directAssets, materialized, knownGuids });
|
|
11418
|
+
}
|
|
11419
|
+
function parentSubject(snapshot, packageId2) {
|
|
11420
|
+
const subject = snapshot.subjects.get(packageKey(packageId2));
|
|
11421
|
+
if (subject === void 0) return void 0;
|
|
11422
|
+
if (subject.format === "source") {
|
|
11423
|
+
return {
|
|
11424
|
+
format: "source",
|
|
11425
|
+
packageId: subject.packageId,
|
|
11426
|
+
parameters: "parameters" in subject.definition ? subject.definition.parameters : []
|
|
11427
|
+
};
|
|
11428
|
+
}
|
|
11429
|
+
if (subject.format === "instance") {
|
|
11430
|
+
return {
|
|
11431
|
+
format: "instance",
|
|
11432
|
+
packageId: subject.packageId,
|
|
11433
|
+
parent: subject.parent,
|
|
11434
|
+
values: subject.values
|
|
11435
|
+
};
|
|
11436
|
+
}
|
|
11437
|
+
return { format: "direct", packageId: subject.packageId };
|
|
11438
|
+
}
|
|
11439
|
+
async function resolveInstance(snapshot, subject) {
|
|
11440
|
+
return resolvePackParameterInheritance(
|
|
11441
|
+
{
|
|
11442
|
+
format: "instance",
|
|
11443
|
+
packageId: subject.packageId,
|
|
11444
|
+
parent: subject.parent,
|
|
11445
|
+
values: subject.values
|
|
11446
|
+
},
|
|
11447
|
+
async (packageId2) => parentSubject(snapshot, packageId2)
|
|
11448
|
+
);
|
|
11449
|
+
}
|
|
11450
|
+
function subjectFor(gameRoot, snapshot, operation) {
|
|
11451
|
+
if (operation.sourcePath !== void 0) {
|
|
11452
|
+
const confined = confinedPath(gameRoot, operation.sourcePath, operation);
|
|
11453
|
+
if (!confined.ok) return confined;
|
|
11454
|
+
const expected = confined.value.relative;
|
|
11455
|
+
const source = [...snapshot.subjects.values()].find(
|
|
11456
|
+
(candidate) => candidate.relativePath === expected
|
|
11457
|
+
);
|
|
11458
|
+
if (source !== void 0) {
|
|
11459
|
+
const requestedPackageId = operation.packageId === void 0 ? void 0 : PackageId.parse(operation.packageId);
|
|
11460
|
+
if (requestedPackageId?.ok === false) {
|
|
11461
|
+
return err(
|
|
11462
|
+
makeError(
|
|
11463
|
+
"pack-package-id-invalid",
|
|
11464
|
+
"a UUID packageId",
|
|
11465
|
+
"repair packageId before querying the Pack subject",
|
|
11466
|
+
{ requestId: operation.requestId, packageId: operation.packageId },
|
|
11467
|
+
operation.packageId
|
|
11468
|
+
)
|
|
11469
|
+
);
|
|
11470
|
+
}
|
|
11471
|
+
if (requestedPackageId?.ok === true && packageKey(requestedPackageId.value) !== packageKey(source.packageId)) {
|
|
11472
|
+
return err(
|
|
11473
|
+
makeError(
|
|
11474
|
+
"pack-parameter-invalid",
|
|
11475
|
+
"sourcePath and packageId to identify the same Pack subject",
|
|
11476
|
+
"remove the conflicting locator or use the packageId returned by asset.list",
|
|
11477
|
+
{
|
|
11478
|
+
requestId: operation.requestId,
|
|
11479
|
+
sourcePath: expected,
|
|
11480
|
+
packageId: operation.packageId,
|
|
11481
|
+
observedPackageId: PackageId.format(source.packageId)
|
|
11482
|
+
}
|
|
11483
|
+
)
|
|
11484
|
+
);
|
|
11485
|
+
}
|
|
11486
|
+
return ok(source);
|
|
11487
|
+
}
|
|
11488
|
+
return err(
|
|
11489
|
+
pathError(
|
|
11490
|
+
"pack-source-not-found",
|
|
11491
|
+
operation,
|
|
11492
|
+
"sourcePath to identify a current Pack subject",
|
|
11493
|
+
"inspect the current Source Index and choose an existing source path",
|
|
11494
|
+
{ sourcePath: expected },
|
|
11495
|
+
expected
|
|
11496
|
+
)
|
|
11497
|
+
);
|
|
11498
|
+
}
|
|
11499
|
+
if (operation.packageId !== void 0) {
|
|
11500
|
+
const parsed = PackageId.parse(operation.packageId);
|
|
11501
|
+
if (!parsed.ok) {
|
|
11502
|
+
return err(
|
|
11503
|
+
makeError(
|
|
11504
|
+
"pack-package-id-invalid",
|
|
11505
|
+
"a UUID packageId",
|
|
11506
|
+
"repair packageId before querying the Pack",
|
|
11507
|
+
{ requestId: operation.requestId, packageId: operation.packageId },
|
|
11508
|
+
operation.packageId
|
|
11509
|
+
)
|
|
11510
|
+
);
|
|
11511
|
+
}
|
|
11512
|
+
const subject = snapshot.subjects.get(packageKey(parsed.value));
|
|
11513
|
+
if (subject !== void 0) return ok(subject);
|
|
11514
|
+
return err(
|
|
11515
|
+
makeError(
|
|
11516
|
+
"pack-source-not-found",
|
|
11517
|
+
"packageId to exist in the current Source Index",
|
|
11518
|
+
"inspect the current source index and choose an existing packageId",
|
|
11519
|
+
{ requestId: operation.requestId, packageId: operation.packageId }
|
|
11520
|
+
)
|
|
11521
|
+
);
|
|
11522
|
+
}
|
|
11523
|
+
if (operation.subject !== void 0 && !isValidAssetGuidString(operation.subject)) {
|
|
11524
|
+
const confined = confinedPath(gameRoot, operation.subject, operation);
|
|
11525
|
+
if (!confined.ok) return confined;
|
|
11526
|
+
const source = [...snapshot.subjects.values()].find(
|
|
11527
|
+
(candidate) => candidate.relativePath === confined.value.relative
|
|
11528
|
+
);
|
|
11529
|
+
if (source !== void 0) return ok(source);
|
|
11530
|
+
}
|
|
11531
|
+
if (operation.subject !== void 0 && isValidAssetGuidString(operation.subject)) {
|
|
11532
|
+
const guid = operation.subject.toLowerCase();
|
|
11533
|
+
const packageSubject = snapshot.subjects.get(guid);
|
|
11534
|
+
if (packageSubject !== void 0) return ok(packageSubject);
|
|
11535
|
+
const asset = [...snapshot.directAssets, ...snapshot.materialized].find(
|
|
11536
|
+
(candidate) => candidate.guid === guid
|
|
11537
|
+
);
|
|
11538
|
+
if (asset !== void 0) {
|
|
11539
|
+
const subject = snapshot.subjects.get(asset.packageId);
|
|
11540
|
+
if (subject !== void 0) return ok(subject);
|
|
11541
|
+
}
|
|
11542
|
+
}
|
|
11543
|
+
return err(
|
|
11544
|
+
makeError(
|
|
11545
|
+
"pack-source-not-found",
|
|
11546
|
+
"a packageId, source path, or known AssetGuid subject",
|
|
11547
|
+
"run asset.list or asset.inspect to obtain a current subject locator",
|
|
11548
|
+
{ requestId: operation.requestId, subject: operation.subject }
|
|
11549
|
+
)
|
|
11550
|
+
);
|
|
11551
|
+
}
|
|
11552
|
+
async function inspectAsset(gameRoot, snapshot, operation) {
|
|
11553
|
+
const selected = subjectFor(gameRoot, snapshot, operation);
|
|
11554
|
+
if (!selected.ok) return selected;
|
|
11555
|
+
const subject = selected.value;
|
|
11556
|
+
if (operation.sourceKey !== void 0) {
|
|
11557
|
+
if (!isValidPackSourceKey(operation.sourceKey)) {
|
|
11558
|
+
return err(
|
|
11559
|
+
makeError(
|
|
11560
|
+
"pack-source-key-invalid",
|
|
11561
|
+
"a stable lower-case sourceKey",
|
|
11562
|
+
"repair sourceKey before inspecting the output identity",
|
|
11563
|
+
{ requestId: operation.requestId, sourceKey: operation.sourceKey },
|
|
11564
|
+
operation.sourceKey
|
|
11565
|
+
)
|
|
11566
|
+
);
|
|
11567
|
+
}
|
|
11568
|
+
if (subject.format === "direct") {
|
|
11569
|
+
const asset = subject.assets.find((candidate) => candidate.sourceKey === operation.sourceKey);
|
|
11570
|
+
if (asset === void 0) {
|
|
11571
|
+
return err(
|
|
11572
|
+
makeError(
|
|
11573
|
+
"pack-output-not-materialized",
|
|
11574
|
+
"sourceKey to exist in the direct Pack",
|
|
11575
|
+
"inspect the current source and choose an existing sourceKey",
|
|
11576
|
+
{
|
|
11577
|
+
requestId: operation.requestId,
|
|
11578
|
+
sourceKey: operation.sourceKey,
|
|
11579
|
+
packageId: PackageId.format(subject.packageId)
|
|
11580
|
+
}
|
|
11581
|
+
)
|
|
11582
|
+
);
|
|
11583
|
+
}
|
|
11584
|
+
const materialized = snapshot.materialized.find(
|
|
11585
|
+
(candidate) => candidate.packageId === packageKey(subject.packageId) && candidate.sourceKey === operation.sourceKey
|
|
11586
|
+
);
|
|
11587
|
+
return ok({
|
|
11588
|
+
...sourceResult(subject, operation),
|
|
11589
|
+
sourceKey: asset.sourceKey,
|
|
11590
|
+
guid: asset.guid,
|
|
11591
|
+
kind: asset.kind,
|
|
11592
|
+
status: materialized === void 0 ? "identity" : materialized.ready ? "ready" : "present"
|
|
11593
|
+
});
|
|
11594
|
+
}
|
|
11595
|
+
try {
|
|
11596
|
+
const guid = AssetGuid.format(AssetGuid.derive(subject.packageId, operation.sourceKey));
|
|
11597
|
+
const materialized = [...snapshot.materialized].find(
|
|
11598
|
+
(candidate) => candidate.packageId === packageKey(subject.packageId) && candidate.sourceKey === operation.sourceKey
|
|
11599
|
+
);
|
|
11600
|
+
return ok({
|
|
11601
|
+
...sourceResult(subject, operation),
|
|
11602
|
+
sourceKey: operation.sourceKey,
|
|
11603
|
+
guid,
|
|
11604
|
+
...materialized === void 0 ? { status: "identity" } : {
|
|
11605
|
+
status: materialized.ready ? "ready" : "present",
|
|
11606
|
+
kind: materialized.kind
|
|
11607
|
+
}
|
|
11608
|
+
});
|
|
11609
|
+
} catch (cause) {
|
|
11610
|
+
return err(
|
|
11611
|
+
makeError(
|
|
11612
|
+
"pack-source-key-invalid",
|
|
11613
|
+
"a valid lower-case sourceKey",
|
|
11614
|
+
"repair sourceKey before inspecting the output identity",
|
|
11615
|
+
{ requestId: operation.requestId, sourceKey: operation.sourceKey, cause: String(cause) },
|
|
11616
|
+
operation.sourceKey
|
|
11617
|
+
)
|
|
11618
|
+
);
|
|
11619
|
+
}
|
|
11620
|
+
}
|
|
11621
|
+
if (subject.format === "instance") {
|
|
11622
|
+
const resolved = await resolveInstance(snapshot, subject);
|
|
11623
|
+
if (!resolved.ok) return resolved;
|
|
11624
|
+
return ok({
|
|
11625
|
+
...sourceResult(subject, operation),
|
|
11626
|
+
parameters: resolved.value.parameters.map((parameter) => ({
|
|
11627
|
+
name: parameter.name,
|
|
11628
|
+
type: parameter.type,
|
|
11629
|
+
default: jsonValue2(parameter.default),
|
|
11630
|
+
...parameter.minimum === void 0 ? {} : { minimum: parameter.minimum },
|
|
11631
|
+
...parameter.maximum === void 0 ? {} : { maximum: parameter.maximum },
|
|
11632
|
+
...parameter.values === void 0 ? {} : { values: parameter.values },
|
|
11633
|
+
...parameter.kind === void 0 ? {} : { kind: parameter.kind }
|
|
11634
|
+
})),
|
|
11635
|
+
effectiveValues: jsonValue2(resolved.value.values),
|
|
11636
|
+
parentChain: resolved.value.parentChain
|
|
11637
|
+
});
|
|
11638
|
+
}
|
|
11639
|
+
return ok(sourceResult(subject, operation));
|
|
11640
|
+
}
|
|
11641
|
+
function listAssets(snapshot, operation) {
|
|
11642
|
+
const assets = snapshotAssets(snapshot).map((asset) => ({
|
|
11643
|
+
packageId: asset.packageId,
|
|
11644
|
+
sourceKey: asset.sourceKey,
|
|
11645
|
+
guid: asset.guid,
|
|
11646
|
+
kind: asset.kind,
|
|
11647
|
+
...asset.name === void 0 ? {} : { name: asset.name },
|
|
11648
|
+
...asset.sourcePath === void 0 ? {} : { sourcePath: asset.sourcePath },
|
|
11649
|
+
status: !("ready" in asset) ? "identity" : asset.ready ? "ready" : "present"
|
|
11650
|
+
})).sort(
|
|
11651
|
+
(left, right) => `${left.packageId}/${left.sourceKey}`.localeCompare(`${right.packageId}/${right.sourceKey}`)
|
|
11652
|
+
);
|
|
11653
|
+
const sources = [...snapshot.subjects.values()].map((subject) => {
|
|
11654
|
+
if (subject.format === "source") {
|
|
11655
|
+
const parameters = serializedParameters(subject.definition);
|
|
11656
|
+
return {
|
|
11657
|
+
packageId: PackageId.format(subject.packageId),
|
|
11658
|
+
sourcePath: subject.relativePath,
|
|
11659
|
+
format: "pack.ts",
|
|
11660
|
+
...parameters === void 0 ? {} : { parameters }
|
|
11661
|
+
};
|
|
11662
|
+
}
|
|
11663
|
+
if (subject.format === "instance") {
|
|
11664
|
+
return {
|
|
11665
|
+
packageId: PackageId.format(subject.packageId),
|
|
11666
|
+
sourcePath: subject.relativePath,
|
|
11667
|
+
format: "instance",
|
|
11668
|
+
parentPackageId: PackageId.format(subject.parent),
|
|
11669
|
+
values: jsonValue2(subject.values)
|
|
11670
|
+
};
|
|
11671
|
+
}
|
|
11672
|
+
return {
|
|
11673
|
+
packageId: PackageId.format(subject.packageId),
|
|
11674
|
+
sourcePath: subject.relativePath,
|
|
11675
|
+
format: "direct"
|
|
11676
|
+
};
|
|
11677
|
+
}).sort(
|
|
11678
|
+
(left, right) => `${left.packageId}/${left.sourcePath}`.localeCompare(
|
|
11679
|
+
`${right.packageId}/${right.sourcePath}`
|
|
11680
|
+
)
|
|
11681
|
+
);
|
|
11682
|
+
return {
|
|
11683
|
+
operation: operation.operation,
|
|
11684
|
+
requestId: operation.requestId,
|
|
11685
|
+
assets,
|
|
11686
|
+
sources,
|
|
11687
|
+
snapshot: { sourceCount: snapshot.subjects.size, assetCount: assets.length }
|
|
11688
|
+
};
|
|
11689
|
+
}
|
|
11690
|
+
function snapshotAssets(snapshot) {
|
|
11691
|
+
const assets = /* @__PURE__ */ new Map();
|
|
11692
|
+
for (const asset of snapshot.directAssets) {
|
|
11693
|
+
assets.set(`${asset.packageId}/${asset.sourceKey}`, asset);
|
|
11694
|
+
}
|
|
11695
|
+
for (const asset of snapshot.materialized) {
|
|
11696
|
+
assets.set(`${asset.packageId}/${asset.sourceKey}`, asset);
|
|
11697
|
+
}
|
|
11698
|
+
return [...assets.values()];
|
|
11699
|
+
}
|
|
11700
|
+
function assetForPair(snapshot, packageId2, sourceKey2) {
|
|
11701
|
+
const key = `${packageKey(packageId2)}/${sourceKey2}`;
|
|
11702
|
+
return snapshotAssets(snapshot).find((asset) => `${asset.packageId}/${asset.sourceKey}` === key);
|
|
11703
|
+
}
|
|
11704
|
+
async function resolveAsset(gameRoot, snapshot, operation) {
|
|
11705
|
+
if (operation.require !== void 0 && operation.require !== "identity" && operation.require !== "present" && operation.require !== "ready") {
|
|
11706
|
+
return err(
|
|
11707
|
+
makeError(
|
|
11708
|
+
"pack-parameter-invalid",
|
|
11709
|
+
"require to be 'identity', 'present', or 'ready'",
|
|
11710
|
+
"choose one of the three Pack identity proof levels",
|
|
11711
|
+
{ requestId: operation.requestId, require: operation.require }
|
|
11712
|
+
)
|
|
11713
|
+
);
|
|
11714
|
+
}
|
|
11715
|
+
let packageId2;
|
|
11716
|
+
let sourceKey2 = operation.sourceKey;
|
|
11717
|
+
let resolvedOutputGuid;
|
|
11718
|
+
if (operation.packageId !== void 0) {
|
|
11719
|
+
const parsed = PackageId.parse(operation.packageId);
|
|
11720
|
+
if (!parsed.ok) {
|
|
11721
|
+
return err(
|
|
11722
|
+
makeError(
|
|
11723
|
+
"pack-package-id-invalid",
|
|
11724
|
+
"a UUID packageId",
|
|
11725
|
+
"repair packageId before resolving a sourceKey",
|
|
11726
|
+
{ requestId: operation.requestId },
|
|
11727
|
+
operation.packageId
|
|
11728
|
+
)
|
|
11729
|
+
);
|
|
11730
|
+
}
|
|
11731
|
+
packageId2 = parsed.value;
|
|
11732
|
+
}
|
|
11733
|
+
if (operation.subject !== void 0 && isValidAssetGuidString(operation.subject)) {
|
|
11734
|
+
const found = [...snapshot.directAssets, ...snapshot.materialized].find(
|
|
11735
|
+
(asset2) => asset2.guid === operation.subject?.toLowerCase()
|
|
11736
|
+
);
|
|
11737
|
+
if (found !== void 0) {
|
|
11738
|
+
const parsed = PackageId.parse(found.packageId);
|
|
11739
|
+
if (parsed.ok) {
|
|
11740
|
+
if (packageId2 !== void 0 && packageKey(packageId2) !== packageKey(parsed.value)) {
|
|
11741
|
+
return err(
|
|
11742
|
+
makeError(
|
|
11743
|
+
"pack-parameter-invalid",
|
|
11744
|
+
"packageId and AssetGuid to identify the same Pack subject",
|
|
11745
|
+
"remove the conflicting locator or resolve the pair from one source",
|
|
11746
|
+
{
|
|
11747
|
+
requestId: operation.requestId,
|
|
11748
|
+
packageId: PackageId.format(packageId2),
|
|
11749
|
+
observedPackageId: found.packageId,
|
|
11750
|
+
guid: operation.subject
|
|
11751
|
+
}
|
|
11752
|
+
)
|
|
11753
|
+
);
|
|
11754
|
+
}
|
|
11755
|
+
if (sourceKey2 !== void 0 && sourceKey2 !== found.sourceKey) {
|
|
11756
|
+
return err(
|
|
11757
|
+
makeError(
|
|
11758
|
+
"pack-parameter-invalid",
|
|
11759
|
+
"sourceKey and AssetGuid to identify the same Pack output",
|
|
11760
|
+
"remove the conflicting locator or use the sourceKey returned by asset.list",
|
|
11761
|
+
{
|
|
11762
|
+
requestId: operation.requestId,
|
|
11763
|
+
sourceKey: sourceKey2,
|
|
11764
|
+
observedSourceKey: found.sourceKey,
|
|
11765
|
+
guid: operation.subject
|
|
11766
|
+
}
|
|
11767
|
+
)
|
|
11768
|
+
);
|
|
11769
|
+
}
|
|
11770
|
+
packageId2 = parsed.value;
|
|
11771
|
+
sourceKey2 ??= found.sourceKey;
|
|
11772
|
+
resolvedOutputGuid = found.guid;
|
|
11773
|
+
}
|
|
11774
|
+
}
|
|
11775
|
+
}
|
|
11776
|
+
if (packageId2 === void 0 && operation.subject !== void 0 && isValidAssetGuidString(operation.subject)) {
|
|
11777
|
+
const parsed = PackageId.parse(operation.subject);
|
|
11778
|
+
if (parsed.ok) packageId2 = parsed.value;
|
|
11779
|
+
}
|
|
11780
|
+
const sourceLocatorCandidate = operation.sourcePath ?? (operation.subject !== void 0 && !isValidAssetGuidString(operation.subject) ? operation.subject : void 0);
|
|
11781
|
+
let sourceLocator;
|
|
11782
|
+
if (sourceLocatorCandidate !== void 0) {
|
|
11783
|
+
const confined = confinedPath(gameRoot, sourceLocatorCandidate, operation);
|
|
11784
|
+
if (!confined.ok) return confined;
|
|
11785
|
+
sourceLocator = confined.value.relative;
|
|
11786
|
+
}
|
|
11787
|
+
if (sourceLocator !== void 0) {
|
|
11788
|
+
const source = [...snapshot.subjects.values()].find(
|
|
11789
|
+
(candidate) => candidate.relativePath === sourceLocator
|
|
11790
|
+
);
|
|
11791
|
+
if (source === void 0) {
|
|
11792
|
+
return err(
|
|
11793
|
+
pathError(
|
|
11794
|
+
"pack-source-not-found",
|
|
11795
|
+
operation,
|
|
11796
|
+
"sourcePath to identify a current Pack subject",
|
|
11797
|
+
"inspect the current Source Index and choose an existing source path",
|
|
11798
|
+
{ sourcePath: sourceLocator },
|
|
11799
|
+
sourceLocator
|
|
11800
|
+
)
|
|
11801
|
+
);
|
|
11802
|
+
}
|
|
11803
|
+
if (packageId2 !== void 0 && packageKey(packageId2) !== packageKey(source.packageId)) {
|
|
11804
|
+
return err(
|
|
11805
|
+
makeError(
|
|
11806
|
+
"pack-parameter-invalid",
|
|
11807
|
+
"sourcePath and packageId to identify the same Pack subject",
|
|
11808
|
+
"remove the conflicting locator or use the packageId returned by asset.list",
|
|
11809
|
+
{
|
|
11810
|
+
requestId: operation.requestId,
|
|
11811
|
+
sourcePath: sourceLocator,
|
|
11812
|
+
packageId: PackageId.format(packageId2),
|
|
11813
|
+
observedPackageId: PackageId.format(source.packageId)
|
|
11814
|
+
}
|
|
11815
|
+
)
|
|
11816
|
+
);
|
|
11817
|
+
}
|
|
11818
|
+
packageId2 ??= source.packageId;
|
|
11819
|
+
}
|
|
11820
|
+
if (packageId2 === void 0 || sourceKey2 === void 0) {
|
|
11821
|
+
return err(
|
|
11822
|
+
makeError(
|
|
11823
|
+
"pack-parameter-invalid",
|
|
11824
|
+
"packageId and sourceKey (or a known output GUID)",
|
|
11825
|
+
"pass packageId + sourceKey, a known AssetGuid, or a source path plus sourceKey",
|
|
11826
|
+
{ requestId: operation.requestId, packageId: operation.packageId, sourceKey: sourceKey2 }
|
|
11827
|
+
)
|
|
11828
|
+
);
|
|
11829
|
+
}
|
|
11830
|
+
if (!isValidPackSourceKey(sourceKey2)) {
|
|
11831
|
+
return err(
|
|
11832
|
+
makeError(
|
|
11833
|
+
"pack-source-key-invalid",
|
|
11834
|
+
"a stable lower-case sourceKey",
|
|
11835
|
+
"repair sourceKey before deriving its AssetGuid",
|
|
11836
|
+
{ requestId: operation.requestId, sourceKey: sourceKey2 },
|
|
11837
|
+
sourceKey2
|
|
11838
|
+
)
|
|
11839
|
+
);
|
|
11840
|
+
}
|
|
11841
|
+
let guid;
|
|
11842
|
+
try {
|
|
11843
|
+
guid = AssetGuid.derive(packageId2, sourceKey2);
|
|
11844
|
+
} catch (cause) {
|
|
11845
|
+
return err(
|
|
11846
|
+
makeError(
|
|
11847
|
+
"pack-source-key-invalid",
|
|
11848
|
+
"a valid packageId and sourceKey pair",
|
|
11849
|
+
"repair the identity pair before resolving",
|
|
11850
|
+
{
|
|
11851
|
+
requestId: operation.requestId,
|
|
11852
|
+
cause: cause instanceof Error ? cause.message : String(cause)
|
|
11853
|
+
}
|
|
11854
|
+
)
|
|
11855
|
+
);
|
|
11856
|
+
}
|
|
11857
|
+
const guidString = AssetGuid.format(guid);
|
|
11858
|
+
if (resolvedOutputGuid !== void 0 && guidString.toLowerCase() !== resolvedOutputGuid) {
|
|
11859
|
+
return err(
|
|
11860
|
+
makeError(
|
|
11861
|
+
"pack-guid-collision",
|
|
11862
|
+
"the known output GUID to equal UUIDv5(packageId, sourceKey)",
|
|
11863
|
+
"rebuild the current generation from the stable identity pair",
|
|
11864
|
+
{
|
|
11865
|
+
requestId: operation.requestId,
|
|
11866
|
+
packageId: PackageId.format(packageId2),
|
|
11867
|
+
sourceKey: sourceKey2,
|
|
11868
|
+
expectedGuid: guidString,
|
|
11869
|
+
observedGuid: resolvedOutputGuid
|
|
11870
|
+
}
|
|
11871
|
+
)
|
|
11872
|
+
);
|
|
11873
|
+
}
|
|
11874
|
+
const asset = assetForPair(snapshot, packageId2, sourceKey2);
|
|
11875
|
+
const materialized = snapshot.materialized.find(
|
|
11876
|
+
(candidate) => candidate.packageId === packageKey(packageId2) && candidate.sourceKey === sourceKey2
|
|
11877
|
+
);
|
|
11878
|
+
const requirement = operation.require ?? "identity";
|
|
11879
|
+
if (requirement === "present" && materialized === void 0) {
|
|
11880
|
+
return err(
|
|
11881
|
+
makeError(
|
|
11882
|
+
"pack-output-not-materialized",
|
|
11883
|
+
"the current build topology to contain this sourceKey",
|
|
11884
|
+
"run rebuild/cold-cook and retry after the current generation publishes the output",
|
|
11885
|
+
{
|
|
11886
|
+
requestId: operation.requestId,
|
|
11887
|
+
packageId: PackageId.format(packageId2),
|
|
11888
|
+
sourceKey: sourceKey2,
|
|
11889
|
+
guid: guidString
|
|
11890
|
+
}
|
|
11891
|
+
)
|
|
11892
|
+
);
|
|
11893
|
+
}
|
|
11894
|
+
if (requirement === "ready" && (materialized === void 0 || !materialized.ready)) {
|
|
11895
|
+
return err(
|
|
11896
|
+
makeError(
|
|
11897
|
+
"asset-not-ready",
|
|
11898
|
+
"current Pack evidence and artifacts for this derived GUID",
|
|
11899
|
+
"inspect producer evidence, then rebuild or cold-cook the same subject",
|
|
11900
|
+
{
|
|
11901
|
+
requestId: operation.requestId,
|
|
11902
|
+
packageId: PackageId.format(packageId2),
|
|
11903
|
+
sourceKey: sourceKey2,
|
|
11904
|
+
guid: guidString
|
|
11905
|
+
}
|
|
11906
|
+
)
|
|
11907
|
+
);
|
|
11908
|
+
}
|
|
11909
|
+
return ok({
|
|
11910
|
+
operation: operation.operation,
|
|
11911
|
+
requestId: operation.requestId,
|
|
11912
|
+
packageId: PackageId.format(packageId2),
|
|
11913
|
+
sourceKey: sourceKey2,
|
|
11914
|
+
guid: guidString,
|
|
11915
|
+
status: materialized === void 0 ? "identity" : materialized.ready ? "ready" : "present",
|
|
11916
|
+
...asset === void 0 ? {} : {
|
|
11917
|
+
...asset.sourcePath === void 0 ? {} : { sourcePath: asset.sourcePath },
|
|
11918
|
+
kind: asset.kind
|
|
11919
|
+
}
|
|
11920
|
+
});
|
|
11921
|
+
}
|
|
11922
|
+
async function verify(snapshot, operation) {
|
|
11923
|
+
for (const subject of snapshot.subjects.values()) {
|
|
11924
|
+
if (subject.format === "instance") {
|
|
11925
|
+
const resolved = await resolveInstance(snapshot, subject);
|
|
11926
|
+
if (!resolved.ok) return err(resolved.error);
|
|
11927
|
+
}
|
|
11928
|
+
if (subject.format === "direct") {
|
|
11929
|
+
for (const asset of subject.assets) {
|
|
11930
|
+
const missing = asset.refs.find((ref) => !snapshot.knownGuids.has(ref.toLowerCase()));
|
|
11931
|
+
if (missing !== void 0) {
|
|
11932
|
+
return err(
|
|
11933
|
+
makeError(
|
|
11934
|
+
"pack-output-reference-missing",
|
|
11935
|
+
"every direct Pack ref to resolve to a known AssetGuid",
|
|
11936
|
+
"repair the payload ref or add the owning external asset before verifying",
|
|
11937
|
+
{
|
|
11938
|
+
requestId: operation.requestId,
|
|
11939
|
+
packageId: PackageId.format(subject.packageId),
|
|
11940
|
+
sourceKey: asset.sourceKey,
|
|
11941
|
+
guid: missing
|
|
11942
|
+
}
|
|
11943
|
+
)
|
|
11944
|
+
);
|
|
11945
|
+
}
|
|
11946
|
+
}
|
|
11947
|
+
}
|
|
11948
|
+
}
|
|
11949
|
+
for (const asset of snapshotAssets(snapshot)) {
|
|
11950
|
+
const missing = asset.refs?.find((ref) => !snapshot.knownGuids.has(ref.toLowerCase()));
|
|
11951
|
+
if (missing !== void 0) {
|
|
11952
|
+
return err(
|
|
11953
|
+
makeError(
|
|
11954
|
+
"pack-output-reference-missing",
|
|
11955
|
+
"every materialized Pack ref to resolve to a known AssetGuid",
|
|
11956
|
+
"repair the published output reference or publish its owning asset before verifying",
|
|
11957
|
+
{
|
|
11958
|
+
requestId: operation.requestId,
|
|
11959
|
+
packageId: asset.packageId,
|
|
11960
|
+
sourceKey: asset.sourceKey,
|
|
11961
|
+
guid: missing
|
|
11962
|
+
}
|
|
11963
|
+
)
|
|
11964
|
+
);
|
|
11965
|
+
}
|
|
11966
|
+
}
|
|
11967
|
+
return ok({
|
|
11968
|
+
operation: operation.operation,
|
|
11969
|
+
requestId: operation.requestId,
|
|
11970
|
+
snapshot: {
|
|
11971
|
+
sourceCount: snapshot.subjects.size,
|
|
11972
|
+
assetCount: snapshotAssets(snapshot).length
|
|
11973
|
+
}
|
|
11974
|
+
});
|
|
11975
|
+
}
|
|
11976
|
+
function packageIdFromOperation(snapshot, operation) {
|
|
11977
|
+
const value = operation.packageId === void 0 ? ok(PackageId.random()) : PackageId.parse(operation.packageId);
|
|
11978
|
+
if (!value.ok) {
|
|
11979
|
+
return err(
|
|
11980
|
+
makeError(
|
|
11981
|
+
"pack-package-id-invalid",
|
|
11982
|
+
"a UUID packageId",
|
|
11983
|
+
"repair packageId or omit it so the gateway can mint one",
|
|
11984
|
+
{ requestId: operation.requestId },
|
|
11985
|
+
operation.packageId
|
|
11986
|
+
)
|
|
11987
|
+
);
|
|
11988
|
+
}
|
|
11989
|
+
const normalized = packageKey(value.value);
|
|
11990
|
+
const alreadyMaterialized = snapshot.materialized.some((asset) => asset.packageId === normalized);
|
|
11991
|
+
return snapshot.subjects.has(normalized) || alreadyMaterialized ? err(
|
|
11992
|
+
makeError(
|
|
11993
|
+
"pack-package-id-collision",
|
|
11994
|
+
"a packageId unused by the current Source Index",
|
|
11995
|
+
"choose a new packageId or use clone without an explicit identity",
|
|
11996
|
+
{ requestId: operation.requestId, packageId: PackageId.format(value.value) }
|
|
11997
|
+
)
|
|
11998
|
+
) : ok(value.value);
|
|
11999
|
+
}
|
|
12000
|
+
async function readConfined(options, operation, sourcePath) {
|
|
12001
|
+
const path = confinedPath(options.gameRoot, sourcePath, operation);
|
|
12002
|
+
if (!path.ok) return path;
|
|
12003
|
+
try {
|
|
12004
|
+
const source = await readFile(path.value.absolute, "utf8");
|
|
12005
|
+
return ok({ ...path.value, source, revision: revisionOf(source) });
|
|
12006
|
+
} catch (cause) {
|
|
12007
|
+
const code = cause.code === "ENOENT" ? "pack-source-not-found" : "pack-source-write-failed";
|
|
12008
|
+
return err(
|
|
12009
|
+
pathError(
|
|
12010
|
+
code,
|
|
12011
|
+
operation,
|
|
12012
|
+
"the requested Pack source to be readable",
|
|
12013
|
+
"restore the source or choose a current locator",
|
|
12014
|
+
{
|
|
12015
|
+
sourcePath: path.value.relative,
|
|
12016
|
+
cause: cause instanceof Error ? cause.message : String(cause)
|
|
12017
|
+
},
|
|
12018
|
+
path.value.relative
|
|
12019
|
+
)
|
|
12020
|
+
);
|
|
12021
|
+
}
|
|
12022
|
+
}
|
|
12023
|
+
function revisionConflict(operation, path, actual) {
|
|
12024
|
+
return makeError(
|
|
12025
|
+
"pack-source-revision-conflict",
|
|
12026
|
+
"expectedRevision to match the current source bytes",
|
|
12027
|
+
"inspect the current source, reconcile the edit, and retry with a new requestId",
|
|
12028
|
+
{
|
|
12029
|
+
requestId: operation.requestId,
|
|
12030
|
+
sourcePath: path,
|
|
12031
|
+
expectedRevision: operation.expectedRevision,
|
|
12032
|
+
actualRevision: actual
|
|
12033
|
+
},
|
|
12034
|
+
actual
|
|
12035
|
+
);
|
|
12036
|
+
}
|
|
12037
|
+
function directJson(packageId2, assets) {
|
|
12038
|
+
return { schemaVersion: "3.0.0", packageId: PackageId.format(packageId2), assets };
|
|
12039
|
+
}
|
|
12040
|
+
function parameterizedScaffold(packageId2, parameters) {
|
|
12041
|
+
const parameterSource = parameters === void 0 ? "" : "\n parameters: " + JSON.stringify(
|
|
12042
|
+
parameters.map((parameter) => jsonValue2(parameter)),
|
|
12043
|
+
null,
|
|
12044
|
+
2
|
|
12045
|
+
).replaceAll("\n", "\n ") + ",";
|
|
12046
|
+
return "import { definePack, definePackageId } from '@forgeax/engine-pack/source';\nimport { ok } from '@forgeax/engine-types';\n\nconst packageId = definePackageId(" + JSON.stringify(PackageId.format(packageId2)) + ");\n\nexport default definePack({\n schemaVersion: '2.0.0',\n packageId," + parameterSource + "\n build: () => ok({}),\n});\n";
|
|
12047
|
+
}
|
|
12048
|
+
function replacePackageIdLiteral(source, packageId2) {
|
|
12049
|
+
const pattern = /(definePackageId\s*\(\s*)(['"])([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})(\2\s*\))/;
|
|
12050
|
+
if (!pattern.test(source)) return void 0;
|
|
12051
|
+
return source.replace(pattern, `$1${JSON.stringify(packageId2)}$4`);
|
|
12052
|
+
}
|
|
12053
|
+
async function inspectAfterWrite(operation, path, source, packageId2, extra = {}) {
|
|
12054
|
+
return ok({
|
|
12055
|
+
operation: operation.operation,
|
|
12056
|
+
requestId: operation.requestId,
|
|
12057
|
+
sourcePath: path.relative,
|
|
12058
|
+
targetPath: path.relative,
|
|
12059
|
+
packageId: PackageId.format(packageId2),
|
|
12060
|
+
revision: revisionOf(source),
|
|
12061
|
+
...extra
|
|
12062
|
+
});
|
|
12063
|
+
}
|
|
12064
|
+
async function executeRaw(options, operation) {
|
|
12065
|
+
if (operation.operation === "asset.list" || operation.operation === "asset.inspect") {
|
|
12066
|
+
const snapshot2 = await createSnapshot(options, operation);
|
|
12067
|
+
if (!snapshot2.ok) return snapshot2;
|
|
12068
|
+
return operation.operation === "asset.list" ? ok(listAssets(snapshot2.value, operation)) : await inspectAsset(options.gameRoot, snapshot2.value, operation);
|
|
12069
|
+
}
|
|
12070
|
+
const snapshot = await createSnapshot(options, operation);
|
|
12071
|
+
if (!snapshot.ok) return snapshot;
|
|
12072
|
+
if (operation.operation === "asset.resolve")
|
|
12073
|
+
return resolveAsset(options.gameRoot, snapshot.value, operation);
|
|
12074
|
+
if (operation.operation === "asset.verify") return verify(snapshot.value, operation);
|
|
12075
|
+
if (operation.operation === "asset-source.create") {
|
|
12076
|
+
const path = confinedPath(
|
|
12077
|
+
options.gameRoot,
|
|
12078
|
+
operation.targetPath ?? operation.sourcePath,
|
|
12079
|
+
operation
|
|
12080
|
+
);
|
|
12081
|
+
if (!path.ok) return path;
|
|
12082
|
+
try {
|
|
12083
|
+
await stat(path.value.absolute);
|
|
12084
|
+
return err(
|
|
12085
|
+
pathError(
|
|
12086
|
+
"pack-source-revision-conflict",
|
|
12087
|
+
operation,
|
|
12088
|
+
"an unused target source path",
|
|
12089
|
+
"inspect the existing source or choose another target path",
|
|
12090
|
+
{ targetPath: path.value.relative },
|
|
12091
|
+
path.value.relative
|
|
12092
|
+
)
|
|
12093
|
+
);
|
|
12094
|
+
} catch (cause) {
|
|
12095
|
+
if (cause.code !== "ENOENT") {
|
|
12096
|
+
return err(
|
|
12097
|
+
pathError(
|
|
12098
|
+
"pack-source-write-failed",
|
|
12099
|
+
operation,
|
|
12100
|
+
"the target path to be available for atomic creation",
|
|
12101
|
+
"repair the filesystem and retry",
|
|
12102
|
+
{ targetPath: path.value.relative, cause: String(cause) }
|
|
12103
|
+
)
|
|
12104
|
+
);
|
|
12105
|
+
}
|
|
12106
|
+
}
|
|
12107
|
+
const identity = packageIdFromOperation(snapshot.value, operation);
|
|
12108
|
+
if (!identity.ok) return identity;
|
|
12109
|
+
const format = operation.format ?? (path.value.relative.endsWith(".pack.json") ? "pack.json" : "pack.ts");
|
|
12110
|
+
if (format === "pack.json" && !path.value.relative.endsWith(".pack.json") || format === "pack.ts" && !path.value.relative.endsWith(".pack.ts")) {
|
|
12111
|
+
return err(
|
|
12112
|
+
makeError(
|
|
12113
|
+
"pack-source-path-invalid",
|
|
12114
|
+
"format and target extension to agree",
|
|
12115
|
+
"use a .pack.ts target for source creation or a .pack.json target for direct data",
|
|
12116
|
+
{ requestId: operation.requestId, format, targetPath: path.value.relative }
|
|
12117
|
+
)
|
|
12118
|
+
);
|
|
12119
|
+
}
|
|
12120
|
+
let source;
|
|
12121
|
+
let extra = { format };
|
|
12122
|
+
if (format === "pack.json") {
|
|
12123
|
+
if (operation.parameters !== void 0 || operation.parent !== void 0 || operation.parentPackageId !== void 0 || operation.values !== void 0) {
|
|
12124
|
+
return err(
|
|
12125
|
+
makeError(
|
|
12126
|
+
"pack-parameter-invalid",
|
|
12127
|
+
"direct create to contain assets only",
|
|
12128
|
+
"use pack.ts for a parameterized source or create-instance for parent+values",
|
|
12129
|
+
{ requestId: operation.requestId }
|
|
12130
|
+
)
|
|
12131
|
+
);
|
|
12132
|
+
}
|
|
12133
|
+
const assets = operation.initialAssets ?? {};
|
|
12134
|
+
const parsed = parseParameterizedPackJson(directJson(identity.value, assets));
|
|
12135
|
+
if (!parsed.ok) return err(parsed.error);
|
|
12136
|
+
if (parsed.value.format !== "direct") {
|
|
12137
|
+
return err(
|
|
12138
|
+
makeError(
|
|
12139
|
+
"pack-parameter-invalid",
|
|
12140
|
+
"direct create to produce a direct v3 Pack document",
|
|
12141
|
+
"use create-instance for parent + values instead of direct assets",
|
|
12142
|
+
{ requestId: operation.requestId }
|
|
12143
|
+
)
|
|
12144
|
+
);
|
|
12145
|
+
}
|
|
12146
|
+
source = `${JSON.stringify(directJson(identity.value, parsed.value.assets), null, 2)}
|
|
12147
|
+
`;
|
|
12148
|
+
} else {
|
|
12149
|
+
if (operation.initialAssets !== void 0 && Object.keys(operation.initialAssets).length > 0) {
|
|
12150
|
+
return err(
|
|
12151
|
+
makeError(
|
|
12152
|
+
"pack-parameter-invalid",
|
|
12153
|
+
"a pack.ts source to define its outputs in build()",
|
|
12154
|
+
"use pack.json for direct assets or omit initialAssets when creating a pack.ts source",
|
|
12155
|
+
{ requestId: operation.requestId }
|
|
12156
|
+
)
|
|
12157
|
+
);
|
|
12158
|
+
}
|
|
12159
|
+
if (operation.parent !== void 0 || operation.parentPackageId !== void 0 || operation.values !== void 0) {
|
|
12160
|
+
return err(
|
|
12161
|
+
makeError(
|
|
12162
|
+
"pack-parameter-invalid",
|
|
12163
|
+
"a new pack.ts source without instance-only parent/value fields",
|
|
12164
|
+
"use asset-source.create-instance for parent + values",
|
|
12165
|
+
{ requestId: operation.requestId }
|
|
12166
|
+
)
|
|
12167
|
+
);
|
|
12168
|
+
}
|
|
12169
|
+
let parameters;
|
|
12170
|
+
if (operation.parameters !== void 0) {
|
|
12171
|
+
const validated = validatePackDefinition({
|
|
12172
|
+
schemaVersion: "2.0.0",
|
|
12173
|
+
packageId: identity.value,
|
|
12174
|
+
parameters: operation.parameters,
|
|
12175
|
+
build: () => ok({})
|
|
12176
|
+
});
|
|
12177
|
+
if (!validated.ok) return err(validated.error);
|
|
12178
|
+
if (!("parameters" in validated.value)) {
|
|
12179
|
+
return err(
|
|
12180
|
+
makeError(
|
|
12181
|
+
"pack-parameter-invalid",
|
|
12182
|
+
"parameters to be non-empty when supplied",
|
|
12183
|
+
"omit parameters for a zero-parameter Pack",
|
|
12184
|
+
{ requestId: operation.requestId }
|
|
12185
|
+
)
|
|
12186
|
+
);
|
|
12187
|
+
}
|
|
12188
|
+
parameters = validated.value.parameters;
|
|
12189
|
+
}
|
|
12190
|
+
source = parameterizedScaffold(identity.value, parameters);
|
|
12191
|
+
const serialized = parameters === void 0 ? void 0 : serializedParameters({
|
|
12192
|
+
schemaVersion: "2.0.0",
|
|
12193
|
+
packageId: identity.value,
|
|
12194
|
+
parameters,
|
|
12195
|
+
build: () => ok({})
|
|
12196
|
+
});
|
|
12197
|
+
extra = {
|
|
12198
|
+
format,
|
|
12199
|
+
...serialized === void 0 ? {} : { parameters: serialized }
|
|
12200
|
+
};
|
|
12201
|
+
}
|
|
12202
|
+
try {
|
|
12203
|
+
await atomicWrite(path.value.absolute, source);
|
|
12204
|
+
} catch (cause) {
|
|
12205
|
+
return err(
|
|
12206
|
+
pathError(
|
|
12207
|
+
"pack-source-write-failed",
|
|
12208
|
+
operation,
|
|
12209
|
+
"the new Pack source to be written atomically",
|
|
12210
|
+
"repair filesystem permissions or disk capacity, then retry with a new requestId",
|
|
12211
|
+
{
|
|
12212
|
+
targetPath: path.value.relative,
|
|
12213
|
+
cause: cause instanceof Error ? cause.message : String(cause)
|
|
12214
|
+
}
|
|
12215
|
+
)
|
|
12216
|
+
);
|
|
12217
|
+
}
|
|
12218
|
+
return inspectAfterWrite(operation, path.value, source, identity.value, extra);
|
|
12219
|
+
}
|
|
12220
|
+
if (operation.operation === "asset-source.clone") {
|
|
12221
|
+
const read = await readConfined(options, operation, operation.sourcePath);
|
|
12222
|
+
if (!read.ok) return read;
|
|
12223
|
+
if (operation.expectedRevision !== void 0 && operation.expectedRevision !== read.value.revision) {
|
|
12224
|
+
return err(revisionConflict(operation, read.value.relative, read.value.revision));
|
|
12225
|
+
}
|
|
12226
|
+
const target = confinedPath(options.gameRoot, operation.targetPath, operation);
|
|
12227
|
+
if (!target.ok) return target;
|
|
12228
|
+
const sourceIsTypeScript = read.value.relative.endsWith(".pack.ts");
|
|
12229
|
+
const targetIsTypeScript = target.value.relative.endsWith(".pack.ts");
|
|
12230
|
+
if (sourceIsTypeScript !== targetIsTypeScript) {
|
|
12231
|
+
return err(
|
|
12232
|
+
makeError(
|
|
12233
|
+
"pack-source-path-invalid",
|
|
12234
|
+
"clone source and target to use the same .pack.ts or .pack.json format",
|
|
12235
|
+
"preserve the source extension when cloning a Pack subject",
|
|
12236
|
+
{
|
|
12237
|
+
requestId: operation.requestId,
|
|
12238
|
+
sourcePath: read.value.relative,
|
|
12239
|
+
targetPath: target.value.relative
|
|
12240
|
+
}
|
|
12241
|
+
)
|
|
12242
|
+
);
|
|
12243
|
+
}
|
|
12244
|
+
try {
|
|
12245
|
+
await stat(target.value.absolute);
|
|
12246
|
+
return err(
|
|
12247
|
+
pathError(
|
|
12248
|
+
"pack-source-revision-conflict",
|
|
12249
|
+
operation,
|
|
12250
|
+
"an unused clone target path",
|
|
12251
|
+
"inspect the target or choose another path",
|
|
12252
|
+
{ targetPath: target.value.relative },
|
|
12253
|
+
target.value.relative
|
|
12254
|
+
)
|
|
12255
|
+
);
|
|
12256
|
+
} catch (cause) {
|
|
12257
|
+
if (cause.code !== "ENOENT") {
|
|
12258
|
+
return err(
|
|
12259
|
+
pathError(
|
|
12260
|
+
"pack-source-write-failed",
|
|
12261
|
+
operation,
|
|
12262
|
+
"the clone target to be writable",
|
|
12263
|
+
"repair filesystem permissions and retry",
|
|
12264
|
+
{ targetPath: target.value.relative, cause: String(cause) }
|
|
12265
|
+
)
|
|
12266
|
+
);
|
|
12267
|
+
}
|
|
12268
|
+
}
|
|
12269
|
+
const identity = packageIdFromOperation(snapshot.value, operation);
|
|
12270
|
+
if (!identity.ok) return identity;
|
|
12271
|
+
let source = read.value.source;
|
|
12272
|
+
if (read.value.relative.endsWith(".pack.json")) {
|
|
12273
|
+
let parsedValue;
|
|
12274
|
+
try {
|
|
12275
|
+
parsedValue = JSON.parse(source);
|
|
12276
|
+
} catch {
|
|
12277
|
+
return err(
|
|
12278
|
+
makeError(
|
|
12279
|
+
"pack-parameter-invalid",
|
|
12280
|
+
"a valid v3 pack.json document",
|
|
12281
|
+
"repair the source before cloning it",
|
|
12282
|
+
{ requestId: operation.requestId, sourcePath: read.value.relative }
|
|
12283
|
+
)
|
|
12284
|
+
);
|
|
12285
|
+
}
|
|
12286
|
+
const parsed = parseParameterizedPackJson(parsedValue);
|
|
12287
|
+
if (!parsed.ok) return err(parsed.error);
|
|
12288
|
+
source = `${JSON.stringify(
|
|
12289
|
+
parsed.value.format === "direct" ? directJson(identity.value, parsed.value.assets) : {
|
|
12290
|
+
schemaVersion: "3.0.0",
|
|
12291
|
+
packageId: PackageId.format(identity.value),
|
|
12292
|
+
parent: PackageId.format(parsed.value.parent),
|
|
12293
|
+
values: parsed.value.values
|
|
12294
|
+
},
|
|
12295
|
+
null,
|
|
12296
|
+
2
|
|
12297
|
+
)}
|
|
12298
|
+
`;
|
|
12299
|
+
} else {
|
|
12300
|
+
const replaced = replacePackageIdLiteral(source, PackageId.format(identity.value));
|
|
12301
|
+
if (replaced === void 0) {
|
|
12302
|
+
return err(
|
|
12303
|
+
makeError(
|
|
12304
|
+
"pack-source-mutation-unsupported",
|
|
12305
|
+
"a constrained definePackageId(UUID) literal in the source",
|
|
12306
|
+
"clone a generated Pack source or create a new Pack; arbitrary TypeScript AST rewriting is unsupported",
|
|
12307
|
+
{ requestId: operation.requestId, sourcePath: read.value.relative }
|
|
12308
|
+
)
|
|
12309
|
+
);
|
|
12310
|
+
}
|
|
12311
|
+
source = replaced;
|
|
12312
|
+
}
|
|
12313
|
+
try {
|
|
12314
|
+
await atomicWrite(target.value.absolute, source);
|
|
12315
|
+
} catch (cause) {
|
|
12316
|
+
return err(
|
|
12317
|
+
pathError(
|
|
12318
|
+
"pack-source-write-failed",
|
|
12319
|
+
operation,
|
|
12320
|
+
"the cloned Pack source to be written atomically",
|
|
12321
|
+
"repair filesystem permissions or disk capacity, then retry",
|
|
12322
|
+
{
|
|
12323
|
+
targetPath: target.value.relative,
|
|
12324
|
+
cause: cause instanceof Error ? cause.message : String(cause)
|
|
12325
|
+
}
|
|
12326
|
+
)
|
|
12327
|
+
);
|
|
12328
|
+
}
|
|
12329
|
+
return inspectAfterWrite(operation, target.value, source, identity.value, {
|
|
12330
|
+
format: target.value.relative.endsWith(".pack.json") ? "pack.json" : "pack.ts"
|
|
12331
|
+
});
|
|
12332
|
+
}
|
|
12333
|
+
if (operation.operation === "asset-source.create-instance") {
|
|
12334
|
+
const target = confinedPath(
|
|
12335
|
+
options.gameRoot,
|
|
12336
|
+
operation.targetPath ?? operation.sourcePath,
|
|
12337
|
+
operation
|
|
12338
|
+
);
|
|
12339
|
+
if (!target.ok) return target;
|
|
12340
|
+
const parentText = operation.parentPackageId ?? operation.parent;
|
|
12341
|
+
if (parentText === void 0) {
|
|
12342
|
+
return err(
|
|
12343
|
+
makeError(
|
|
12344
|
+
"pack-parent-not-found",
|
|
12345
|
+
"a parent packageId for the new instance",
|
|
12346
|
+
"pass parentPackageId or parent and point it at a parameterized source",
|
|
12347
|
+
{ requestId: operation.requestId }
|
|
12348
|
+
)
|
|
12349
|
+
);
|
|
12350
|
+
}
|
|
12351
|
+
const parentId = PackageId.parse(parentText);
|
|
12352
|
+
if (!parentId.ok) {
|
|
12353
|
+
return err(
|
|
12354
|
+
makeError(
|
|
12355
|
+
"pack-package-id-invalid",
|
|
12356
|
+
"a UUID parent packageId",
|
|
12357
|
+
"repair the parent package identity",
|
|
12358
|
+
{ requestId: operation.requestId },
|
|
12359
|
+
parentText
|
|
12360
|
+
)
|
|
12361
|
+
);
|
|
12362
|
+
}
|
|
12363
|
+
const parent = snapshot.value.subjects.get(packageKey(parentId.value));
|
|
12364
|
+
if (parent === void 0) {
|
|
12365
|
+
return err(
|
|
12366
|
+
makeError(
|
|
12367
|
+
"pack-parent-not-found",
|
|
12368
|
+
"the parent packageId to exist in the current Source Index",
|
|
12369
|
+
"inspect the Source Index and choose a parameterized parent",
|
|
12370
|
+
{ requestId: operation.requestId, parent: parentText }
|
|
12371
|
+
)
|
|
12372
|
+
);
|
|
12373
|
+
}
|
|
12374
|
+
if (parent.format === "source" && !("parameters" in parent.definition)) {
|
|
12375
|
+
return err(
|
|
12376
|
+
makeError(
|
|
12377
|
+
"pack-parent-not-parameterized",
|
|
12378
|
+
"a non-empty parameterized Pack source as the parent",
|
|
12379
|
+
"use asset-source.clone for a zero-parameter Pack",
|
|
12380
|
+
{ requestId: operation.requestId, parent: parentText }
|
|
12381
|
+
)
|
|
12382
|
+
);
|
|
12383
|
+
}
|
|
12384
|
+
if (parent.format === "direct") {
|
|
12385
|
+
return err(
|
|
12386
|
+
makeError(
|
|
12387
|
+
"pack-parent-not-parameterized",
|
|
12388
|
+
"a parameterized Pack source or instance as the parent",
|
|
12389
|
+
"direct Packs cannot be instance parents",
|
|
12390
|
+
{ requestId: operation.requestId, parent: parentText }
|
|
12391
|
+
)
|
|
12392
|
+
);
|
|
12393
|
+
}
|
|
12394
|
+
try {
|
|
12395
|
+
await stat(target.value.absolute);
|
|
12396
|
+
return err(
|
|
12397
|
+
pathError(
|
|
12398
|
+
"pack-source-revision-conflict",
|
|
12399
|
+
operation,
|
|
12400
|
+
"an unused instance target path",
|
|
12401
|
+
"inspect the existing instance or choose another path",
|
|
12402
|
+
{ targetPath: target.value.relative },
|
|
12403
|
+
target.value.relative
|
|
12404
|
+
)
|
|
12405
|
+
);
|
|
12406
|
+
} catch (cause) {
|
|
12407
|
+
if (cause.code !== "ENOENT") {
|
|
12408
|
+
return err(
|
|
12409
|
+
pathError(
|
|
12410
|
+
"pack-source-write-failed",
|
|
12411
|
+
operation,
|
|
12412
|
+
"the instance target to be writable",
|
|
12413
|
+
"repair filesystem permissions and retry",
|
|
12414
|
+
{ targetPath: target.value.relative, cause: String(cause) }
|
|
12415
|
+
)
|
|
12416
|
+
);
|
|
12417
|
+
}
|
|
12418
|
+
}
|
|
12419
|
+
const identity = packageIdFromOperation(snapshot.value, operation);
|
|
12420
|
+
if (!identity.ok) return identity;
|
|
12421
|
+
const values = operation.values ?? {};
|
|
12422
|
+
const serializedValues = jsonValue2(values);
|
|
12423
|
+
const candidate = {
|
|
12424
|
+
format: "instance",
|
|
12425
|
+
packageId: identity.value,
|
|
12426
|
+
parent: parentId.value,
|
|
12427
|
+
values,
|
|
12428
|
+
sourcePath: target.value.absolute,
|
|
12429
|
+
relativePath: target.value.relative
|
|
12430
|
+
};
|
|
12431
|
+
const withCandidate = {
|
|
12432
|
+
...snapshot.value,
|
|
12433
|
+
subjects: new Map([...snapshot.value.subjects, [packageKey(identity.value), candidate]])
|
|
12434
|
+
};
|
|
12435
|
+
const resolved = await resolveInstance(withCandidate, candidate);
|
|
12436
|
+
if (!resolved.ok) return err(resolved.error);
|
|
12437
|
+
const source = `${JSON.stringify(
|
|
12438
|
+
{
|
|
12439
|
+
schemaVersion: "3.0.0",
|
|
12440
|
+
packageId: PackageId.format(identity.value),
|
|
12441
|
+
parent: PackageId.format(parentId.value),
|
|
12442
|
+
values: serializedValues
|
|
12443
|
+
},
|
|
12444
|
+
null,
|
|
12445
|
+
2
|
|
12446
|
+
)}
|
|
12447
|
+
`;
|
|
12448
|
+
try {
|
|
12449
|
+
await atomicWrite(target.value.absolute, source);
|
|
12450
|
+
} catch (cause) {
|
|
12451
|
+
return err(
|
|
12452
|
+
pathError(
|
|
12453
|
+
"pack-source-write-failed",
|
|
12454
|
+
operation,
|
|
12455
|
+
"the new instance to be written atomically",
|
|
12456
|
+
"repair filesystem permissions or disk capacity, then retry",
|
|
12457
|
+
{
|
|
12458
|
+
targetPath: target.value.relative,
|
|
12459
|
+
cause: cause instanceof Error ? cause.message : String(cause)
|
|
12460
|
+
}
|
|
12461
|
+
)
|
|
12462
|
+
);
|
|
12463
|
+
}
|
|
12464
|
+
return inspectAfterWrite(operation, target.value, source, identity.value, {
|
|
12465
|
+
format: "instance",
|
|
12466
|
+
parentPackageId: PackageId.format(parentId.value),
|
|
12467
|
+
values: serializedValues,
|
|
12468
|
+
effectiveValues: jsonValue2(resolved.value.values),
|
|
12469
|
+
parentChain: resolved.value.parentChain
|
|
12470
|
+
});
|
|
12471
|
+
}
|
|
12472
|
+
if (operation.operation === "asset-source.apply-values") {
|
|
12473
|
+
const read = await readConfined(options, operation, operation.sourcePath);
|
|
12474
|
+
if (!read.ok) return read;
|
|
12475
|
+
if (operation.expectedRevision === void 0 || operation.expectedRevision !== read.value.revision) {
|
|
12476
|
+
return err(revisionConflict(operation, read.value.relative, read.value.revision));
|
|
12477
|
+
}
|
|
12478
|
+
let json;
|
|
12479
|
+
try {
|
|
12480
|
+
json = JSON.parse(read.value.source);
|
|
12481
|
+
} catch {
|
|
12482
|
+
return err(
|
|
12483
|
+
makeError(
|
|
12484
|
+
"pack-parameter-invalid",
|
|
12485
|
+
"a valid v3 instance JSON document",
|
|
12486
|
+
"repair the source before applying values",
|
|
12487
|
+
{ requestId: operation.requestId, sourcePath: read.value.relative }
|
|
12488
|
+
)
|
|
12489
|
+
);
|
|
12490
|
+
}
|
|
12491
|
+
const parsed = parseParameterizedPackJson(json);
|
|
12492
|
+
if (!parsed.ok) return err(parsed.error);
|
|
12493
|
+
if (parsed.value.format !== "instance") {
|
|
12494
|
+
return err(
|
|
12495
|
+
makeError(
|
|
12496
|
+
"pack-parameter-invalid",
|
|
12497
|
+
"an instance pack.json subject",
|
|
12498
|
+
"apply-values only edits parent+values instances",
|
|
12499
|
+
{ requestId: operation.requestId, sourcePath: read.value.relative }
|
|
12500
|
+
)
|
|
12501
|
+
);
|
|
12502
|
+
}
|
|
12503
|
+
const values = operation.values ?? {};
|
|
12504
|
+
const serializedValues = jsonValue2(values);
|
|
12505
|
+
const candidate = {
|
|
12506
|
+
format: "instance",
|
|
12507
|
+
packageId: parsed.value.packageId,
|
|
12508
|
+
parent: parsed.value.parent,
|
|
12509
|
+
values,
|
|
12510
|
+
sourcePath: read.value.absolute,
|
|
12511
|
+
relativePath: read.value.relative
|
|
12512
|
+
};
|
|
12513
|
+
const withCandidate = {
|
|
12514
|
+
...snapshot.value,
|
|
12515
|
+
subjects: new Map([...snapshot.value.subjects, [packageKey(candidate.packageId), candidate]])
|
|
12516
|
+
};
|
|
12517
|
+
const resolved = await resolveInstance(withCandidate, candidate);
|
|
12518
|
+
if (!resolved.ok) return err(resolved.error);
|
|
12519
|
+
const source = `${JSON.stringify(
|
|
12520
|
+
{
|
|
12521
|
+
schemaVersion: "3.0.0",
|
|
12522
|
+
packageId: PackageId.format(parsed.value.packageId),
|
|
12523
|
+
parent: PackageId.format(parsed.value.parent),
|
|
12524
|
+
values: serializedValues
|
|
12525
|
+
},
|
|
12526
|
+
null,
|
|
12527
|
+
2
|
|
12528
|
+
)}
|
|
12529
|
+
`;
|
|
12530
|
+
try {
|
|
12531
|
+
await atomicWrite(read.value.absolute, source);
|
|
12532
|
+
} catch (cause) {
|
|
12533
|
+
return err(
|
|
12534
|
+
pathError(
|
|
12535
|
+
"pack-source-write-failed",
|
|
12536
|
+
operation,
|
|
12537
|
+
"the updated instance to be written atomically",
|
|
12538
|
+
"repair filesystem permissions or disk capacity, then retry with a new requestId",
|
|
12539
|
+
{
|
|
12540
|
+
sourcePath: read.value.relative,
|
|
12541
|
+
cause: cause instanceof Error ? cause.message : String(cause)
|
|
12542
|
+
}
|
|
12543
|
+
)
|
|
12544
|
+
);
|
|
12545
|
+
}
|
|
12546
|
+
return inspectAfterWrite(operation, read.value, source, parsed.value.packageId, {
|
|
12547
|
+
format: "instance",
|
|
12548
|
+
parentPackageId: PackageId.format(parsed.value.parent),
|
|
12549
|
+
values: serializedValues,
|
|
12550
|
+
effectiveValues: jsonValue2(resolved.value.values),
|
|
12551
|
+
parentChain: resolved.value.parentChain
|
|
12552
|
+
});
|
|
12553
|
+
}
|
|
12554
|
+
if (operation.operation === "asset-source.rebuild" || operation.operation === "asset-source.cold-cook") {
|
|
12555
|
+
const read = await readConfined(options, operation, operation.sourcePath);
|
|
12556
|
+
if (!read.ok) return read;
|
|
12557
|
+
if (operation.expectedRevision === void 0 || operation.expectedRevision !== read.value.revision) {
|
|
12558
|
+
return err(revisionConflict(operation, read.value.relative, read.value.revision));
|
|
12559
|
+
}
|
|
12560
|
+
const rebuilt = await options.rebuild?.(
|
|
12561
|
+
read.value.relative,
|
|
12562
|
+
operation.operation === "asset-source.rebuild" ? "rebuild" : "cold-cook"
|
|
12563
|
+
);
|
|
12564
|
+
if (rebuilt === void 0) {
|
|
12565
|
+
return err(
|
|
12566
|
+
makeError(
|
|
12567
|
+
"pack-source-mutation-unsupported",
|
|
12568
|
+
"a build-owner callback for rebuild or cold-cook",
|
|
12569
|
+
"connect the gateway to the project build owner before requesting a mutation",
|
|
12570
|
+
{ requestId: operation.requestId, sourcePath: read.value.relative }
|
|
12571
|
+
)
|
|
12572
|
+
);
|
|
12573
|
+
}
|
|
12574
|
+
if (!rebuilt.ok) return err(rebuilt.error);
|
|
12575
|
+
const refreshed = await readConfined(options, operation, operation.sourcePath);
|
|
12576
|
+
if (!refreshed.ok) return refreshed;
|
|
12577
|
+
const refreshedSnapshot = await createSnapshot(options, operation);
|
|
12578
|
+
if (!refreshedSnapshot.ok) return refreshedSnapshot;
|
|
12579
|
+
const selected = subjectFor(options.gameRoot, refreshedSnapshot.value, operation);
|
|
12580
|
+
if (!selected.ok) return selected;
|
|
12581
|
+
return inspectAfterWrite(
|
|
12582
|
+
operation,
|
|
12583
|
+
refreshed.value,
|
|
12584
|
+
refreshed.value.source,
|
|
12585
|
+
selected.value.packageId,
|
|
12586
|
+
{
|
|
12587
|
+
format: refreshed.value.relative.endsWith(".pack.json") ? "pack.json" : "pack.ts"
|
|
12588
|
+
}
|
|
12589
|
+
);
|
|
12590
|
+
}
|
|
12591
|
+
return err(
|
|
12592
|
+
makeError(
|
|
12593
|
+
"pack-parameter-invalid",
|
|
12594
|
+
"a supported parameterized Pack operation",
|
|
12595
|
+
"use one of PARAMETERIZED_PACK_OPERATION_IDS",
|
|
12596
|
+
{ requestId: operation.requestId, operation: operation.operation }
|
|
12597
|
+
)
|
|
12598
|
+
);
|
|
12599
|
+
}
|
|
12600
|
+
function createFileSystemParameterizedPackAuthoringPort(options) {
|
|
12601
|
+
return { execute: (operation) => executeRaw(options, operation) };
|
|
12602
|
+
}
|
|
12603
|
+
function createFileSystemParameterizedPackAuthoringGateway(options) {
|
|
12604
|
+
return createParameterizedPackAuthoringGateway(
|
|
12605
|
+
createFileSystemParameterizedPackAuthoringPort(options)
|
|
12606
|
+
);
|
|
12607
|
+
}
|
|
10095
12608
|
function parsePackV2(value) {
|
|
10096
12609
|
if (!validatePackV2(value)) {
|
|
10097
12610
|
return err({
|
|
@@ -10107,8 +12620,8 @@ function stable(value) {
|
|
|
10107
12620
|
if (value instanceof Uint8Array) return `bytes:${Buffer.from(value).toString("base64")}`;
|
|
10108
12621
|
if (Array.isArray(value)) return `[${value.map(stable).join(",")}]`;
|
|
10109
12622
|
if (value !== null && typeof value === "object") {
|
|
10110
|
-
const
|
|
10111
|
-
return `{${Object.keys(
|
|
12623
|
+
const record2 = value;
|
|
12624
|
+
return `{${Object.keys(record2).sort().map((key) => `${JSON.stringify(key)}:${stable(record2[key])}`).join(",")}}`;
|
|
10112
12625
|
}
|
|
10113
12626
|
return JSON.stringify(value) ?? "null";
|
|
10114
12627
|
}
|
|
@@ -10212,6 +12725,6 @@ function createRuntimePackPublication(input) {
|
|
|
10212
12725
|
};
|
|
10213
12726
|
}
|
|
10214
12727
|
|
|
10215
|
-
export { MESH_BIN_DIGEST_BYTES, MESH_BIN_HEADER_V4_BYTES, MESH_BIN_PROJECTION_VERSION, MESH_BIN_VERSION,
|
|
12728
|
+
export { AssetGuid, MESH_BIN_DIGEST_BYTES, MESH_BIN_HEADER_V4_BYTES, MESH_BIN_PROJECTION_VERSION, MESH_BIN_VERSION, PACK_PARAMETER_TYPES, PACK_SOURCE_KEY_RE, PARAMETERIZED_PACK_OPERATION_DESCRIPTORS, PARAMETERIZED_PACK_OPERATION_IDS, PackageId, SCRIPTABLE_PACK_ASSET_KINDS, STANDARD_SCRIPTABLE_PACK_SCAN_OPTIONS, buildCatalogProjection, buildOfflineAssetEvidence, calculateCatalogDelta, calculateTopologyDiff, catalogProjectionFor, catalogSourcePathFor, collectMaterialCookRefs, createFileSystemParameterizedPackAuthoringGateway, createFileSystemParameterizedPackAuthoringPort, createMaterialArtifactDigest, createParameterizedPackAuthoringGateway, createRuntimePackPublication, currentProjectionFor, decodeMeshBinHeader, definePack, definePackageId, diffTopology, finalizePackageProduct, finalizePackageTransportSource, findReservedAssetKindConflict, inventoryDigest, isParameterizedPack, isScriptablePackAssetKind, isValidAssetGuidString, isValidPackSourceKey, metaPathForGuid, packageTransportRevision, packageVerification, parsePackAuthoringJson, parsePackJson, parsePackV2, parseParameterizedPackJson, projectAssetRefs, projectCookedMaterialRecord, projectCookedPackageEntry, projectDirectPackJson, projectExternalCatalogEntries, projectPackageCatalog, projectParameterizedPackMeta, projectRuntimeCatalogRow, projectSceneEntityRefs, projectScriptablePackSceneComponents, resolveAssetSource, resolvePackInheritance, resolvePackParameterInheritance, resolvePackParameterValues, scanInventory, serializeCookedMaterialRecord, serializeMaterialCookReceipt, syncAuthorInventory, validateArtifactPath, validateAuthorInventory, validateCookedMaterialRecord, validateMaterialCookReceipt, validateMeta, validatePack, validatePackDefinition, validatePackV2, validateProducerContract, validateProducerOutputs, writeMeshBinHeader };
|
|
10216
12729
|
//# sourceMappingURL=build.mjs.map
|
|
10217
12730
|
//# sourceMappingURL=build.mjs.map
|