@forgeax/engine-pack 0.1.21 → 0.1.24
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 +167 -48
- package/dist/__tests__/inventory-schema.test.d.ts +2 -0
- package/dist/__tests__/inventory-schema.test.d.ts.map +1 -0
- package/dist/__tests__/material-cook-receipt-layer-plan.unit.test.d.ts +2 -0
- package/dist/__tests__/material-cook-receipt-layer-plan.unit.test.d.ts.map +1 -0
- package/dist/__tests__/pack-authoring-gateway.unit.test.d.ts +2 -0
- package/dist/__tests__/pack-authoring-gateway.unit.test.d.ts.map +1 -0
- package/dist/__tests__/pack-authoring.unit.test.d.ts +2 -0
- package/dist/__tests__/pack-authoring.unit.test.d.ts.map +1 -0
- package/dist/__tests__/pack-scanner.unit.test.d.ts +2 -0
- package/dist/__tests__/pack-scanner.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 +3449 -897
- 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 +1361 -845
- 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 +11 -0
- 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 +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +1297 -562
- 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.d.ts +1 -1
- package/dist/material-cook.d.ts.map +1 -1
- package/dist/material-cook.mjs +50 -3
- package/dist/material-cook.mjs.map +1 -1
- package/dist/name.mjs +4 -7
- package/dist/name.mjs.map +1 -1
- package/dist/pack-authoring-node.d.ts +26 -0
- package/dist/pack-authoring-node.d.ts.map +1 -0
- package/dist/pack-authoring-node.mjs +11089 -0
- package/dist/pack-authoring-node.mjs.map +1 -0
- package/dist/pack-authoring.d.ts +230 -0
- package/dist/pack-authoring.d.ts.map +1 -0
- package/dist/pack-authoring.mjs +1137 -0
- package/dist/pack-authoring.mjs.map +1 -0
- package/dist/package-finalizer.d.ts +2 -20
- package/dist/package-finalizer.d.ts.map +1 -1
- 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 +18 -7
- package/dist/scanner.d.ts.map +1 -1
- package/dist/scanner.mjs +1164 -687
- 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 +7 -31
- package/dist/scriptable-pack-node.d.ts.map +1 -1
- package/dist/scriptable-pack-node.mjs +572 -1019
- 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 +20 -532
- package/dist/scriptable-pack.d.ts.map +1 -1
- package/dist/scriptable-pack.mjs +1038 -527
- package/dist/scriptable-pack.mjs.map +1 -1
- package/package.json +2 -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__/material-cook-receipt-layer-plan.unit.test.ts +16 -0
- package/src/__tests__/material-cook-schema.unit.test.ts +62 -0
- package/src/__tests__/pack-authoring-gateway.unit.test.ts +249 -0
- package/src/__tests__/pack-authoring.unit.test.ts +266 -0
- package/src/__tests__/pack-scanner.unit.test.ts +123 -0
- package/src/__tests__/pack.unit.test.ts +1 -238
- package/src/__tests__/package-finalizer.contract.test.ts +55 -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 +11 -14
- package/src/__tests__/scanner-inventory.test.ts +23 -10
- 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 +60 -33
- package/src/cli-asset.ts +68 -83
- package/src/deriveAssetName.ts +14 -13
- package/src/evidence/material-cook.ts +79 -3
- package/src/evidence/source-inventory.ts +34 -21
- package/src/guid.ts +65 -4
- package/src/index.ts +15 -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/material-cook.ts +1 -0
- package/src/pack-authoring-node.ts +1966 -0
- package/src/pack-authoring.ts +1478 -0
- package/src/package-finalizer.ts +2 -42
- package/src/resolve-asset-source.ts +4 -76
- package/src/scanner.ts +236 -56
- package/src/schema/material-cook.schema.json +4 -1
- package/src/schema-compiled.ts +2 -0
- package/src/scriptable-pack-node.ts +108 -719
- package/src/scriptable-pack-worker.ts +48 -16
- package/src/scriptable-pack.ts +28 -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/scanner.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { createHash } from 'crypto';
|
|
2
2
|
import { stat, readFile, readdir, realpath, mkdtemp, rm } from 'fs/promises';
|
|
3
|
-
import { join, basename, dirname, resolve,
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { join, basename, dirname, resolve, extname } from 'path';
|
|
4
|
+
import { ok, PACK_ERROR_HINTS, err, validateSourceOverrideMap, AssetError, ImportError } from '@forgeax/engine-types';
|
|
5
|
+
import { sha1 } from '@noble/hashes/legacy.js';
|
|
6
6
|
import { uuidv7obj } from 'uuidv7';
|
|
7
|
+
import { existsSync } from 'fs';
|
|
7
8
|
import { tmpdir } from 'os';
|
|
8
9
|
import { fileURLToPath } from 'url';
|
|
9
10
|
import { Worker } from 'worker_threads';
|
|
@@ -3625,49 +3626,49 @@ var require_fast_uri = __commonJS({
|
|
|
3625
3626
|
schemelessOptions.skipEscape = true;
|
|
3626
3627
|
return serialize(resolved, schemelessOptions);
|
|
3627
3628
|
}
|
|
3628
|
-
function resolveComponent(base,
|
|
3629
|
+
function resolveComponent(base, relative, options, skipNormalization) {
|
|
3629
3630
|
const target = {};
|
|
3630
3631
|
if (!skipNormalization) {
|
|
3631
3632
|
base = parse(serialize(base, options), options);
|
|
3632
|
-
|
|
3633
|
+
relative = parse(serialize(relative, options), options);
|
|
3633
3634
|
}
|
|
3634
3635
|
options = options || {};
|
|
3635
|
-
if (!options.tolerant &&
|
|
3636
|
-
target.scheme =
|
|
3637
|
-
target.userinfo =
|
|
3638
|
-
target.host =
|
|
3639
|
-
target.port =
|
|
3640
|
-
target.path = removeDotSegments(
|
|
3641
|
-
target.query =
|
|
3636
|
+
if (!options.tolerant && relative.scheme) {
|
|
3637
|
+
target.scheme = relative.scheme;
|
|
3638
|
+
target.userinfo = relative.userinfo;
|
|
3639
|
+
target.host = relative.host;
|
|
3640
|
+
target.port = relative.port;
|
|
3641
|
+
target.path = removeDotSegments(relative.path || "");
|
|
3642
|
+
target.query = relative.query;
|
|
3642
3643
|
} else {
|
|
3643
|
-
if (
|
|
3644
|
-
target.userinfo =
|
|
3645
|
-
target.host =
|
|
3646
|
-
target.port =
|
|
3647
|
-
target.path = removeDotSegments(
|
|
3648
|
-
target.query =
|
|
3644
|
+
if (relative.userinfo !== void 0 || relative.host !== void 0 || relative.port !== void 0) {
|
|
3645
|
+
target.userinfo = relative.userinfo;
|
|
3646
|
+
target.host = relative.host;
|
|
3647
|
+
target.port = relative.port;
|
|
3648
|
+
target.path = removeDotSegments(relative.path || "");
|
|
3649
|
+
target.query = relative.query;
|
|
3649
3650
|
} else {
|
|
3650
|
-
if (!
|
|
3651
|
+
if (!relative.path) {
|
|
3651
3652
|
target.path = base.path;
|
|
3652
|
-
if (
|
|
3653
|
-
target.query =
|
|
3653
|
+
if (relative.query !== void 0) {
|
|
3654
|
+
target.query = relative.query;
|
|
3654
3655
|
} else {
|
|
3655
3656
|
target.query = base.query;
|
|
3656
3657
|
}
|
|
3657
3658
|
} else {
|
|
3658
|
-
if (
|
|
3659
|
-
target.path = removeDotSegments(
|
|
3659
|
+
if (relative.path[0] === "/") {
|
|
3660
|
+
target.path = removeDotSegments(relative.path);
|
|
3660
3661
|
} else {
|
|
3661
3662
|
if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) {
|
|
3662
|
-
target.path = "/" +
|
|
3663
|
+
target.path = "/" + relative.path;
|
|
3663
3664
|
} else if (!base.path) {
|
|
3664
|
-
target.path =
|
|
3665
|
+
target.path = relative.path;
|
|
3665
3666
|
} else {
|
|
3666
|
-
target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) +
|
|
3667
|
+
target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative.path;
|
|
3667
3668
|
}
|
|
3668
3669
|
target.path = removeDotSegments(target.path);
|
|
3669
3670
|
}
|
|
3670
|
-
target.query =
|
|
3671
|
+
target.query = relative.query;
|
|
3671
3672
|
}
|
|
3672
3673
|
target.userinfo = base.userinfo;
|
|
3673
3674
|
target.host = base.host;
|
|
@@ -3675,7 +3676,7 @@ var require_fast_uri = __commonJS({
|
|
|
3675
3676
|
}
|
|
3676
3677
|
target.scheme = base.scheme;
|
|
3677
3678
|
}
|
|
3678
|
-
target.fragment =
|
|
3679
|
+
target.fragment = relative.fragment;
|
|
3679
3680
|
return target;
|
|
3680
3681
|
}
|
|
3681
3682
|
function equal(uriA, uriB, options) {
|
|
@@ -4714,8 +4715,8 @@ var require_multipleOf = __commonJS({
|
|
|
4714
4715
|
const { gen, data, schemaCode, it } = cxt;
|
|
4715
4716
|
const prec = it.opts.multipleOfPrecision;
|
|
4716
4717
|
const res = gen.let("res");
|
|
4717
|
-
const
|
|
4718
|
-
cxt.fail$data((0, codegen_1._)`(${schemaCode} === 0 || (${res} = ${data}/${schemaCode}, ${
|
|
4718
|
+
const invalid = prec ? (0, codegen_1._)`Math.abs(Math.round(${res}) - ${res}) > 1e-${prec}` : (0, codegen_1._)`${res} !== parseInt(${res})`;
|
|
4719
|
+
cxt.fail$data((0, codegen_1._)`(${schemaCode} === 0 || (${res} = ${data}/${schemaCode}, ${invalid}))`);
|
|
4719
4720
|
}
|
|
4720
4721
|
};
|
|
4721
4722
|
exports.default = def;
|
|
@@ -6820,27 +6821,6 @@ var require_dist = __commonJS({
|
|
|
6820
6821
|
exports.default = formatsPlugin;
|
|
6821
6822
|
}
|
|
6822
6823
|
});
|
|
6823
|
-
function loadAssetConfig(cwd) {
|
|
6824
|
-
let pkg;
|
|
6825
|
-
try {
|
|
6826
|
-
pkg = JSON.parse(readFileSync(join(cwd, "package.json"), "utf-8"));
|
|
6827
|
-
} catch {
|
|
6828
|
-
return { roots: [join(cwd, "assets")], paths: {} };
|
|
6829
|
-
}
|
|
6830
|
-
const assets = pkg.forgeax?.assets;
|
|
6831
|
-
const rawRoots = assets?.roots;
|
|
6832
|
-
const roots = Array.isArray(rawRoots) && rawRoots.length > 0 ? rawRoots.map((r) => join(cwd, r)) : [join(cwd, "assets")];
|
|
6833
|
-
const rawPaths = assets?.paths;
|
|
6834
|
-
const paths = {};
|
|
6835
|
-
if (rawPaths !== void 0 && rawPaths !== null && typeof rawPaths === "object") {
|
|
6836
|
-
for (const [name, dir] of Object.entries(rawPaths)) {
|
|
6837
|
-
if (typeof dir === "string") {
|
|
6838
|
-
paths[name] = join(cwd, dir);
|
|
6839
|
-
}
|
|
6840
|
-
}
|
|
6841
|
-
}
|
|
6842
|
-
return { roots, paths };
|
|
6843
|
-
}
|
|
6844
6824
|
|
|
6845
6825
|
// src/errors.ts
|
|
6846
6826
|
var PackError = class extends Error {
|
|
@@ -6866,6 +6846,10 @@ function bytesToDashForm(bytes) {
|
|
|
6866
6846
|
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]]}`;
|
|
6867
6847
|
}
|
|
6868
6848
|
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
6849
|
+
var PACK_SOURCE_KEY_RE = /^[a-z0-9][a-z0-9._-]*(\/[a-z0-9][a-z0-9._-]*)*$/;
|
|
6850
|
+
function isValidPackSourceKey(value) {
|
|
6851
|
+
return typeof value === "string" && PACK_SOURCE_KEY_RE.test(value);
|
|
6852
|
+
}
|
|
6869
6853
|
function isValidAssetGuidString(value) {
|
|
6870
6854
|
return typeof value === "string" && UUID_RE.test(value);
|
|
6871
6855
|
}
|
|
@@ -6877,6 +6861,48 @@ function dashFormToBytes(dashForm) {
|
|
|
6877
6861
|
}
|
|
6878
6862
|
return bytes;
|
|
6879
6863
|
}
|
|
6864
|
+
function randomUuidBytes() {
|
|
6865
|
+
const uuid = uuidv7obj();
|
|
6866
|
+
const bytes = new Uint8Array(16);
|
|
6867
|
+
bytes.set(uuid.bytes);
|
|
6868
|
+
return bytes;
|
|
6869
|
+
}
|
|
6870
|
+
function packageId(value) {
|
|
6871
|
+
return value;
|
|
6872
|
+
}
|
|
6873
|
+
var PackageId = {
|
|
6874
|
+
parse(dashForm) {
|
|
6875
|
+
const parsed = AssetGuid.parse(dashForm);
|
|
6876
|
+
return parsed.ok ? { ok: true, value: packageId(parsed.value) } : parsed;
|
|
6877
|
+
},
|
|
6878
|
+
format(value) {
|
|
6879
|
+
return bytesToDashForm(value);
|
|
6880
|
+
},
|
|
6881
|
+
random() {
|
|
6882
|
+
return packageId(randomUuidBytes());
|
|
6883
|
+
}
|
|
6884
|
+
};
|
|
6885
|
+
function derivedGuid(namespace, sourceKey) {
|
|
6886
|
+
if (!(namespace instanceof Uint8Array) || namespace.byteLength !== 16) {
|
|
6887
|
+
throw new TypeError("AssetGuid.derive requires a 16-byte PackageId");
|
|
6888
|
+
}
|
|
6889
|
+
if (!isValidPackSourceKey(sourceKey)) {
|
|
6890
|
+
const error = new TypeError(
|
|
6891
|
+
`AssetGuid.derive received invalid sourceKey ${JSON.stringify(sourceKey)}`
|
|
6892
|
+
);
|
|
6893
|
+
Object.defineProperty(error, "code", { value: "pack-source-key-invalid" });
|
|
6894
|
+
throw error;
|
|
6895
|
+
}
|
|
6896
|
+
const name = new TextEncoder().encode(sourceKey);
|
|
6897
|
+
const input = new Uint8Array(namespace.byteLength + name.byteLength);
|
|
6898
|
+
input.set(namespace, 0);
|
|
6899
|
+
input.set(name, namespace.byteLength);
|
|
6900
|
+
const digest = sha1(input);
|
|
6901
|
+
const result = digest.slice(0, 16);
|
|
6902
|
+
result[6] = (result[6] ?? 0) & 15 | 80;
|
|
6903
|
+
result[8] = (result[8] ?? 0) & 63 | 128;
|
|
6904
|
+
return brand(result);
|
|
6905
|
+
}
|
|
6880
6906
|
var AssetGuid = {
|
|
6881
6907
|
/**
|
|
6882
6908
|
* Parse a 36-char RFC 4122 dash-form UUID string into an AssetGuid.
|
|
@@ -6920,19 +6946,758 @@ var AssetGuid = {
|
|
|
6920
6946
|
* Works in both Node.js and browser environments.
|
|
6921
6947
|
*/
|
|
6922
6948
|
random() {
|
|
6923
|
-
|
|
6924
|
-
|
|
6925
|
-
|
|
6926
|
-
|
|
6949
|
+
return brand(randomUuidBytes());
|
|
6950
|
+
},
|
|
6951
|
+
/** Derive the stable UUIDv5 projection for one Pack subject and sourceKey. */
|
|
6952
|
+
derive(namespace, sourceKey) {
|
|
6953
|
+
return derivedGuid(namespace, sourceKey);
|
|
6927
6954
|
}
|
|
6928
6955
|
};
|
|
6956
|
+
var PACK_PARAMETER_TYPES = [
|
|
6957
|
+
"bool",
|
|
6958
|
+
"u32",
|
|
6959
|
+
"i32",
|
|
6960
|
+
"f32",
|
|
6961
|
+
"f64",
|
|
6962
|
+
"string",
|
|
6963
|
+
"enum",
|
|
6964
|
+
"vec2",
|
|
6965
|
+
"vec3",
|
|
6966
|
+
"vec4",
|
|
6967
|
+
"color",
|
|
6968
|
+
"asset-guid"
|
|
6969
|
+
];
|
|
6970
|
+
function authoringError(code, expected, hint, detail = {}, actual) {
|
|
6971
|
+
return {
|
|
6972
|
+
code,
|
|
6973
|
+
expected,
|
|
6974
|
+
hint,
|
|
6975
|
+
...actual === void 0 ? {} : { actual },
|
|
6976
|
+
detail
|
|
6977
|
+
};
|
|
6978
|
+
}
|
|
6979
|
+
function failure(error) {
|
|
6980
|
+
return err(error);
|
|
6981
|
+
}
|
|
6929
6982
|
function isRecord(value) {
|
|
6983
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
6984
|
+
}
|
|
6985
|
+
function validateSceneComponents(value) {
|
|
6986
|
+
if (value === void 0) return ok(void 0);
|
|
6987
|
+
if (!Array.isArray(value)) {
|
|
6988
|
+
return failure(
|
|
6989
|
+
parameterFailure(
|
|
6990
|
+
"$.sceneComponents",
|
|
6991
|
+
"an array of component schema records",
|
|
6992
|
+
value,
|
|
6993
|
+
"sceneComponents is not an array"
|
|
6994
|
+
)
|
|
6995
|
+
);
|
|
6996
|
+
}
|
|
6997
|
+
const components = [];
|
|
6998
|
+
const names = /* @__PURE__ */ new Set();
|
|
6999
|
+
for (const [componentIndex, candidate] of value.entries()) {
|
|
7000
|
+
if (!isRecord(candidate) || typeof candidate.name !== "string" || !isRecord(candidate.fields)) {
|
|
7001
|
+
return failure(
|
|
7002
|
+
parameterFailure(
|
|
7003
|
+
`$.sceneComponents[${componentIndex}]`,
|
|
7004
|
+
"a component record with name and fields",
|
|
7005
|
+
candidate,
|
|
7006
|
+
"scene component schema is malformed"
|
|
7007
|
+
)
|
|
7008
|
+
);
|
|
7009
|
+
}
|
|
7010
|
+
if (candidate.name.length === 0 || names.has(candidate.name)) {
|
|
7011
|
+
return failure(
|
|
7012
|
+
parameterFailure(
|
|
7013
|
+
`$.sceneComponents[${componentIndex}].name`,
|
|
7014
|
+
"a non-empty unique component name",
|
|
7015
|
+
candidate.name,
|
|
7016
|
+
"scene component names must be unique"
|
|
7017
|
+
)
|
|
7018
|
+
);
|
|
7019
|
+
}
|
|
7020
|
+
names.add(candidate.name);
|
|
7021
|
+
const fields = {};
|
|
7022
|
+
for (const [fieldName, field] of Object.entries(candidate.fields)) {
|
|
7023
|
+
if (typeof field === "string" && field.length === 0 || typeof field !== "string" && (!isRecord(field) || typeof field.type !== "string" || field.type.length === 0)) {
|
|
7024
|
+
return failure(
|
|
7025
|
+
parameterFailure(
|
|
7026
|
+
`$.sceneComponents[${componentIndex}].fields.${fieldName}`,
|
|
7027
|
+
"a field type string or { type: string }",
|
|
7028
|
+
field,
|
|
7029
|
+
"scene component field schema is malformed"
|
|
7030
|
+
)
|
|
7031
|
+
);
|
|
7032
|
+
}
|
|
7033
|
+
fields[fieldName] = field;
|
|
7034
|
+
}
|
|
7035
|
+
components.push({ name: candidate.name, fields });
|
|
7036
|
+
}
|
|
7037
|
+
return ok(components);
|
|
7038
|
+
}
|
|
7039
|
+
function isPackageId(value) {
|
|
7040
|
+
return value instanceof Uint8Array && value.byteLength === 16;
|
|
7041
|
+
}
|
|
7042
|
+
function cloneValue(value) {
|
|
7043
|
+
if (value instanceof Uint8Array) return value.slice();
|
|
7044
|
+
if (Array.isArray(value)) return value.map((item) => cloneValue(item));
|
|
7045
|
+
return value;
|
|
7046
|
+
}
|
|
7047
|
+
function sourceKeyFailure(sourceKey, propertyPath = "$.sourceKey") {
|
|
7048
|
+
return authoringError(
|
|
7049
|
+
"pack-source-key-invalid",
|
|
7050
|
+
"a sourceKey matching ^[a-z0-9][a-z0-9._-]*(/[a-z0-9][a-z0-9._-]*)*$",
|
|
7051
|
+
"use a stable lower-case semantic key; do not derive it from file paths or output order",
|
|
7052
|
+
{ propertyPath, sourceKey },
|
|
7053
|
+
typeof sourceKey === "string" ? sourceKey : void 0
|
|
7054
|
+
);
|
|
7055
|
+
}
|
|
7056
|
+
function parameterFailure(propertyPath, expected, actual, reason) {
|
|
7057
|
+
return authoringError(
|
|
7058
|
+
"pack-parameter-invalid",
|
|
7059
|
+
expected,
|
|
7060
|
+
"repair the parameter declaration or the instance values, then inspect and rebuild",
|
|
7061
|
+
{ propertyPath, reason, actual: typeof actual === "string" ? actual : JSON.stringify(actual) }
|
|
7062
|
+
);
|
|
7063
|
+
}
|
|
7064
|
+
function numericType(type) {
|
|
7065
|
+
return type === "u32" || type === "i32" || type === "f32" || type === "f64";
|
|
7066
|
+
}
|
|
7067
|
+
function vectorLength(type) {
|
|
7068
|
+
switch (type) {
|
|
7069
|
+
case "vec2":
|
|
7070
|
+
return 2;
|
|
7071
|
+
case "vec3":
|
|
7072
|
+
return 3;
|
|
7073
|
+
case "vec4":
|
|
7074
|
+
case "color":
|
|
7075
|
+
return 4;
|
|
7076
|
+
default:
|
|
7077
|
+
return void 0;
|
|
7078
|
+
}
|
|
7079
|
+
}
|
|
7080
|
+
function parameterValueError(parameter, value, propertyPath) {
|
|
7081
|
+
const { type } = parameter;
|
|
7082
|
+
if (type === "bool" && typeof value !== "boolean") {
|
|
7083
|
+
return parameterFailure(propertyPath, "a boolean", value, "bool value has the wrong type");
|
|
7084
|
+
}
|
|
7085
|
+
if (numericType(type)) {
|
|
7086
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
7087
|
+
return parameterFailure(
|
|
7088
|
+
propertyPath,
|
|
7089
|
+
"a finite number",
|
|
7090
|
+
value,
|
|
7091
|
+
"numeric value is not finite"
|
|
7092
|
+
);
|
|
7093
|
+
}
|
|
7094
|
+
if ((type === "u32" || type === "i32") && !Number.isInteger(value)) {
|
|
7095
|
+
return parameterFailure(
|
|
7096
|
+
propertyPath,
|
|
7097
|
+
"an integer",
|
|
7098
|
+
value,
|
|
7099
|
+
"integer parameter received a fraction"
|
|
7100
|
+
);
|
|
7101
|
+
}
|
|
7102
|
+
if (type === "u32" && (value < 0 || value > 4294967295)) {
|
|
7103
|
+
return parameterFailure(
|
|
7104
|
+
propertyPath,
|
|
7105
|
+
"an unsigned 32-bit integer",
|
|
7106
|
+
value,
|
|
7107
|
+
"u32 value is outside [0, 2^32 - 1]"
|
|
7108
|
+
);
|
|
7109
|
+
}
|
|
7110
|
+
if (type === "i32" && (value < -2147483648 || value > 2147483647)) {
|
|
7111
|
+
return parameterFailure(
|
|
7112
|
+
propertyPath,
|
|
7113
|
+
"a signed 32-bit integer",
|
|
7114
|
+
value,
|
|
7115
|
+
"i32 value is outside [-2^31, 2^31 - 1]"
|
|
7116
|
+
);
|
|
7117
|
+
}
|
|
7118
|
+
if (type === "f32" && !Number.isFinite(Math.fround(value))) {
|
|
7119
|
+
return parameterFailure(
|
|
7120
|
+
propertyPath,
|
|
7121
|
+
"a finite IEEE-754 32-bit float",
|
|
7122
|
+
value,
|
|
7123
|
+
"f32 value overflows binary32"
|
|
7124
|
+
);
|
|
7125
|
+
}
|
|
7126
|
+
if (parameter.minimum !== void 0 && value < parameter.minimum) {
|
|
7127
|
+
return parameterFailure(
|
|
7128
|
+
propertyPath,
|
|
7129
|
+
`a number >= ${parameter.minimum}`,
|
|
7130
|
+
value,
|
|
7131
|
+
"value is below minimum"
|
|
7132
|
+
);
|
|
7133
|
+
}
|
|
7134
|
+
if (parameter.maximum !== void 0 && value > parameter.maximum) {
|
|
7135
|
+
return parameterFailure(
|
|
7136
|
+
propertyPath,
|
|
7137
|
+
`a number <= ${parameter.maximum}`,
|
|
7138
|
+
value,
|
|
7139
|
+
"value is above maximum"
|
|
7140
|
+
);
|
|
7141
|
+
}
|
|
7142
|
+
return void 0;
|
|
7143
|
+
}
|
|
7144
|
+
if (type === "string" && typeof value !== "string") {
|
|
7145
|
+
return parameterFailure(propertyPath, "a string", value, "string parameter has the wrong type");
|
|
7146
|
+
}
|
|
7147
|
+
if (type === "enum") {
|
|
7148
|
+
if (typeof value !== "string") {
|
|
7149
|
+
return parameterFailure(
|
|
7150
|
+
propertyPath,
|
|
7151
|
+
"one of the declared enum strings",
|
|
7152
|
+
value,
|
|
7153
|
+
"enum value has the wrong type"
|
|
7154
|
+
);
|
|
7155
|
+
}
|
|
7156
|
+
if (parameter.values === void 0 || !parameter.values.includes(value)) {
|
|
7157
|
+
return parameterFailure(
|
|
7158
|
+
propertyPath,
|
|
7159
|
+
"one of the declared enum values",
|
|
7160
|
+
value,
|
|
7161
|
+
"enum value is not declared"
|
|
7162
|
+
);
|
|
7163
|
+
}
|
|
7164
|
+
return void 0;
|
|
7165
|
+
}
|
|
7166
|
+
const length = vectorLength(type);
|
|
7167
|
+
if (length !== void 0) {
|
|
7168
|
+
if (!Array.isArray(value) || value.length !== length || value.some((component) => typeof component !== "number" || !Number.isFinite(component))) {
|
|
7169
|
+
return parameterFailure(
|
|
7170
|
+
propertyPath,
|
|
7171
|
+
`a finite numeric vector with ${length} components`,
|
|
7172
|
+
value,
|
|
7173
|
+
"vector value has the wrong shape"
|
|
7174
|
+
);
|
|
7175
|
+
}
|
|
7176
|
+
if (type === "color" && value.some((component) => component < 0 || component > 1)) {
|
|
7177
|
+
return parameterFailure(
|
|
7178
|
+
propertyPath,
|
|
7179
|
+
"an RGBA color with components in [0, 1]",
|
|
7180
|
+
value,
|
|
7181
|
+
"color component is outside [0, 1]"
|
|
7182
|
+
);
|
|
7183
|
+
}
|
|
7184
|
+
return void 0;
|
|
7185
|
+
}
|
|
7186
|
+
if (type === "asset-guid") {
|
|
7187
|
+
const validString = typeof value === "string" && isValidAssetGuidString(value);
|
|
7188
|
+
if (!(value instanceof Uint8Array && value.byteLength === 16) && !validString) {
|
|
7189
|
+
return parameterFailure(
|
|
7190
|
+
propertyPath,
|
|
7191
|
+
"a 16-byte AssetGuid or UUID string",
|
|
7192
|
+
value,
|
|
7193
|
+
"asset GUID value is malformed"
|
|
7194
|
+
);
|
|
7195
|
+
}
|
|
7196
|
+
return void 0;
|
|
7197
|
+
}
|
|
7198
|
+
return parameterFailure(
|
|
7199
|
+
propertyPath,
|
|
7200
|
+
"a supported Pack parameter type",
|
|
7201
|
+
value,
|
|
7202
|
+
"unknown parameter type"
|
|
7203
|
+
);
|
|
7204
|
+
}
|
|
7205
|
+
function normalizeParameterValue(parameter, value, propertyPath) {
|
|
7206
|
+
const error = parameterValueError(parameter, value, propertyPath);
|
|
7207
|
+
if (error !== void 0) return failure(error);
|
|
7208
|
+
if (parameter.type === "asset-guid" && typeof value === "string") {
|
|
7209
|
+
const parsed = AssetGuid.parse(value);
|
|
7210
|
+
if (!parsed.ok) {
|
|
7211
|
+
return failure(
|
|
7212
|
+
parameterFailure(
|
|
7213
|
+
propertyPath,
|
|
7214
|
+
"a valid AssetGuid UUID string",
|
|
7215
|
+
value,
|
|
7216
|
+
"asset GUID parser rejected the value"
|
|
7217
|
+
)
|
|
7218
|
+
);
|
|
7219
|
+
}
|
|
7220
|
+
return ok(parsed.value);
|
|
7221
|
+
}
|
|
7222
|
+
return ok(cloneValue(value));
|
|
7223
|
+
}
|
|
7224
|
+
function validateParameterDefinitions(parameters, propertyPath = "$.parameters") {
|
|
7225
|
+
if (!Array.isArray(parameters) || parameters.length === 0) {
|
|
7226
|
+
return failure(
|
|
7227
|
+
parameterFailure(
|
|
7228
|
+
propertyPath,
|
|
7229
|
+
"a non-empty parameter descriptor array",
|
|
7230
|
+
parameters,
|
|
7231
|
+
"parameters must be explicit and non-empty"
|
|
7232
|
+
)
|
|
7233
|
+
);
|
|
7234
|
+
}
|
|
7235
|
+
const names = /* @__PURE__ */ new Set();
|
|
7236
|
+
const normalized = [];
|
|
7237
|
+
for (const [index, candidate] of parameters.entries()) {
|
|
7238
|
+
const path = `${propertyPath}[${index}]`;
|
|
7239
|
+
if (!isRecord(candidate))
|
|
7240
|
+
return failure(
|
|
7241
|
+
parameterFailure(
|
|
7242
|
+
path,
|
|
7243
|
+
"a parameter descriptor object",
|
|
7244
|
+
candidate,
|
|
7245
|
+
"descriptor is not an object"
|
|
7246
|
+
)
|
|
7247
|
+
);
|
|
7248
|
+
const name = candidate.name;
|
|
7249
|
+
if (typeof name !== "string" || !/^[A-Za-z][A-Za-z0-9_.-]*$/.test(name)) {
|
|
7250
|
+
return failure(
|
|
7251
|
+
parameterFailure(
|
|
7252
|
+
`${path}.name`,
|
|
7253
|
+
"a unique identifier-like parameter name",
|
|
7254
|
+
name,
|
|
7255
|
+
"parameter name is invalid"
|
|
7256
|
+
)
|
|
7257
|
+
);
|
|
7258
|
+
}
|
|
7259
|
+
if (names.has(name))
|
|
7260
|
+
return failure(
|
|
7261
|
+
parameterFailure(
|
|
7262
|
+
`${path}.name`,
|
|
7263
|
+
"a unique parameter name",
|
|
7264
|
+
name,
|
|
7265
|
+
"parameter name is duplicated"
|
|
7266
|
+
)
|
|
7267
|
+
);
|
|
7268
|
+
names.add(name);
|
|
7269
|
+
const unknown = Object.keys(candidate).find(
|
|
7270
|
+
(key) => !["name", "type", "default", "minimum", "maximum", "values", "kind"].includes(key)
|
|
7271
|
+
);
|
|
7272
|
+
if (unknown !== void 0) {
|
|
7273
|
+
return failure(
|
|
7274
|
+
parameterFailure(
|
|
7275
|
+
`${path}.${unknown}`,
|
|
7276
|
+
"only name, type, default, minimum, maximum, values, and kind fields",
|
|
7277
|
+
candidate[unknown],
|
|
7278
|
+
"parameter descriptors are a closed authoring schema"
|
|
7279
|
+
)
|
|
7280
|
+
);
|
|
7281
|
+
}
|
|
7282
|
+
const type = candidate.type;
|
|
7283
|
+
if (typeof type !== "string" || !PACK_PARAMETER_TYPES.includes(type)) {
|
|
7284
|
+
return failure(
|
|
7285
|
+
parameterFailure(
|
|
7286
|
+
`${path}.type`,
|
|
7287
|
+
PACK_PARAMETER_TYPES.join(" | "),
|
|
7288
|
+
type,
|
|
7289
|
+
"parameter type is not supported"
|
|
7290
|
+
)
|
|
7291
|
+
);
|
|
7292
|
+
}
|
|
7293
|
+
const typed = {
|
|
7294
|
+
...candidate,
|
|
7295
|
+
name,
|
|
7296
|
+
type
|
|
7297
|
+
};
|
|
7298
|
+
if (typed.values !== void 0) {
|
|
7299
|
+
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) {
|
|
7300
|
+
return failure(
|
|
7301
|
+
parameterFailure(
|
|
7302
|
+
`${path}.values`,
|
|
7303
|
+
"unique non-empty strings for enum",
|
|
7304
|
+
typed.values,
|
|
7305
|
+
"enum values are malformed"
|
|
7306
|
+
)
|
|
7307
|
+
);
|
|
7308
|
+
}
|
|
7309
|
+
} else if (typed.type === "enum") {
|
|
7310
|
+
return failure(
|
|
7311
|
+
parameterFailure(
|
|
7312
|
+
`${path}.values`,
|
|
7313
|
+
"a non-empty enum choices array",
|
|
7314
|
+
typed.values,
|
|
7315
|
+
"enum has no choices"
|
|
7316
|
+
)
|
|
7317
|
+
);
|
|
7318
|
+
}
|
|
7319
|
+
if (typed.kind !== void 0 && (typed.type !== "asset-guid" || typeof typed.kind !== "string")) {
|
|
7320
|
+
return failure(
|
|
7321
|
+
parameterFailure(
|
|
7322
|
+
`${path}.kind`,
|
|
7323
|
+
"a kind constraint only on asset-guid parameters",
|
|
7324
|
+
typed.kind,
|
|
7325
|
+
"kind is misplaced"
|
|
7326
|
+
)
|
|
7327
|
+
);
|
|
7328
|
+
}
|
|
7329
|
+
for (const field of ["minimum", "maximum"]) {
|
|
7330
|
+
const bound = typed[field];
|
|
7331
|
+
if (bound !== void 0 && (typeof bound !== "number" || !Number.isFinite(bound))) {
|
|
7332
|
+
return failure(
|
|
7333
|
+
parameterFailure(
|
|
7334
|
+
`${path}.${field}`,
|
|
7335
|
+
"a finite numeric bound",
|
|
7336
|
+
bound,
|
|
7337
|
+
"numeric bound is invalid"
|
|
7338
|
+
)
|
|
7339
|
+
);
|
|
7340
|
+
}
|
|
7341
|
+
}
|
|
7342
|
+
if (!numericType(typed.type) && (typed.minimum !== void 0 || typed.maximum !== void 0)) {
|
|
7343
|
+
return failure(
|
|
7344
|
+
parameterFailure(
|
|
7345
|
+
path,
|
|
7346
|
+
"minimum/maximum only on numeric parameters",
|
|
7347
|
+
typed,
|
|
7348
|
+
"numeric bounds are not meaningful for this parameter type"
|
|
7349
|
+
)
|
|
7350
|
+
);
|
|
7351
|
+
}
|
|
7352
|
+
if (typed.minimum !== void 0 && typed.maximum !== void 0 && typed.minimum > typed.maximum) {
|
|
7353
|
+
return failure(
|
|
7354
|
+
parameterFailure(path, "minimum <= maximum", typed, "numeric bounds are reversed")
|
|
7355
|
+
);
|
|
7356
|
+
}
|
|
7357
|
+
const defaultResult = normalizeParameterValue(typed, typed.default, `${path}.default`);
|
|
7358
|
+
if (!defaultResult.ok) return defaultResult;
|
|
7359
|
+
normalized.push({
|
|
7360
|
+
...typed,
|
|
7361
|
+
default: defaultResult.value,
|
|
7362
|
+
...typed.values === void 0 ? {} : { values: Object.freeze([...typed.values]) }
|
|
7363
|
+
});
|
|
7364
|
+
}
|
|
7365
|
+
return ok(Object.freeze(normalized));
|
|
7366
|
+
}
|
|
7367
|
+
function projectScriptablePackMeta(definition, sourcePath) {
|
|
7368
|
+
return {
|
|
7369
|
+
schemaVersion: "2.0.0",
|
|
7370
|
+
kind: "scriptable-pack-source",
|
|
7371
|
+
packageId: PackageId.format(definition.packageId),
|
|
7372
|
+
source: sourcePath,
|
|
7373
|
+
..."parameters" in definition ? {
|
|
7374
|
+
parameters: definition.parameters.map((parameter) => ({
|
|
7375
|
+
name: parameter.name,
|
|
7376
|
+
type: parameter.type,
|
|
7377
|
+
default: jsonParameterValue(parameter.default),
|
|
7378
|
+
...parameter.minimum === void 0 ? {} : { minimum: parameter.minimum },
|
|
7379
|
+
...parameter.maximum === void 0 ? {} : { maximum: parameter.maximum },
|
|
7380
|
+
...parameter.values === void 0 ? {} : { values: parameter.values },
|
|
7381
|
+
...parameter.kind === void 0 ? {} : { kind: parameter.kind }
|
|
7382
|
+
}))
|
|
7383
|
+
} : {}
|
|
7384
|
+
};
|
|
7385
|
+
}
|
|
7386
|
+
function jsonParameterValue(value) {
|
|
7387
|
+
return value instanceof Uint8Array ? AssetGuid.format(value) : value;
|
|
7388
|
+
}
|
|
7389
|
+
function validatePackDefinition(value, sourcePath) {
|
|
7390
|
+
if (!isRecord(value))
|
|
7391
|
+
return failure(
|
|
7392
|
+
parameterFailure("$", "a Pack definition object", value, "definition is not an object")
|
|
7393
|
+
);
|
|
7394
|
+
const unknown = Object.keys(value).find(
|
|
7395
|
+
(key) => !["schemaVersion", "packageId", "name", "parameters", "sceneComponents", "build"].includes(
|
|
7396
|
+
key
|
|
7397
|
+
)
|
|
7398
|
+
);
|
|
7399
|
+
if (unknown !== void 0) {
|
|
7400
|
+
return failure(
|
|
7401
|
+
parameterFailure(
|
|
7402
|
+
`$.${unknown}`,
|
|
7403
|
+
"only schemaVersion, packageId, name, parameters, sceneComponents, and build fields",
|
|
7404
|
+
value[unknown],
|
|
7405
|
+
"legacy static output declarations and external asset tables are not part of v2 authoring"
|
|
7406
|
+
)
|
|
7407
|
+
);
|
|
7408
|
+
}
|
|
7409
|
+
if (value.schemaVersion !== "2.0.0") {
|
|
7410
|
+
return failure(
|
|
7411
|
+
parameterFailure(
|
|
7412
|
+
"$.schemaVersion",
|
|
7413
|
+
"the literal '2.0.0'",
|
|
7414
|
+
value.schemaVersion,
|
|
7415
|
+
"authoring source schema is unsupported"
|
|
7416
|
+
)
|
|
7417
|
+
);
|
|
7418
|
+
}
|
|
7419
|
+
if (!isPackageId(value.packageId)) {
|
|
7420
|
+
return failure(
|
|
7421
|
+
authoringError(
|
|
7422
|
+
"pack-package-id-invalid",
|
|
7423
|
+
"a 16-byte PackageId",
|
|
7424
|
+
"use definePackageId() for the stable source identity",
|
|
7425
|
+
{ sourcePath, propertyPath: "$.packageId" },
|
|
7426
|
+
typeof value.packageId === "string" ? value.packageId : void 0
|
|
7427
|
+
)
|
|
7428
|
+
);
|
|
7429
|
+
}
|
|
7430
|
+
if (value.name !== void 0 && typeof value.name !== "string") {
|
|
7431
|
+
return failure(
|
|
7432
|
+
parameterFailure("$.name", "a string when present", value.name, "display name is malformed")
|
|
7433
|
+
);
|
|
7434
|
+
}
|
|
7435
|
+
if (typeof value.build !== "function") {
|
|
7436
|
+
return failure(
|
|
7437
|
+
parameterFailure("$.build", "a build function", value.build, "build is not callable")
|
|
7438
|
+
);
|
|
7439
|
+
}
|
|
7440
|
+
const sceneComponents = validateSceneComponents(value.sceneComponents);
|
|
7441
|
+
if (!sceneComponents.ok) return sceneComponents;
|
|
7442
|
+
const hasParameters = Object.hasOwn(value, "parameters");
|
|
7443
|
+
if (!hasParameters) {
|
|
7444
|
+
return ok(
|
|
7445
|
+
Object.freeze({
|
|
7446
|
+
schemaVersion: "2.0.0",
|
|
7447
|
+
packageId: value.packageId,
|
|
7448
|
+
...value.name === void 0 ? {} : { name: value.name },
|
|
7449
|
+
...sceneComponents.value === void 0 ? {} : { sceneComponents: sceneComponents.value },
|
|
7450
|
+
build: value.build
|
|
7451
|
+
})
|
|
7452
|
+
);
|
|
7453
|
+
}
|
|
7454
|
+
const parameters = validateParameterDefinitions(value.parameters);
|
|
7455
|
+
if (!parameters.ok) return parameters;
|
|
7456
|
+
return ok(
|
|
7457
|
+
Object.freeze({
|
|
7458
|
+
schemaVersion: "2.0.0",
|
|
7459
|
+
packageId: value.packageId,
|
|
7460
|
+
...value.name === void 0 ? {} : { name: value.name },
|
|
7461
|
+
...sceneComponents.value === void 0 ? {} : { sceneComponents: sceneComponents.value },
|
|
7462
|
+
parameters: parameters.value,
|
|
7463
|
+
build: value.build
|
|
7464
|
+
})
|
|
7465
|
+
);
|
|
7466
|
+
}
|
|
7467
|
+
function jsonError(propertyPath, expected, actual, reason) {
|
|
7468
|
+
return failure(
|
|
7469
|
+
authoringError(
|
|
7470
|
+
"pack-parameter-invalid",
|
|
7471
|
+
expected,
|
|
7472
|
+
"repair the v3 pack.json authoring data, then rerun scan or rebuild",
|
|
7473
|
+
{
|
|
7474
|
+
propertyPath,
|
|
7475
|
+
reason,
|
|
7476
|
+
actual: typeof actual === "string" ? actual : JSON.stringify(actual)
|
|
7477
|
+
}
|
|
7478
|
+
)
|
|
7479
|
+
);
|
|
7480
|
+
}
|
|
7481
|
+
function parsePackageId(value, propertyPath) {
|
|
7482
|
+
if (typeof value !== "string") {
|
|
7483
|
+
return failure(
|
|
7484
|
+
authoringError(
|
|
7485
|
+
"pack-package-id-invalid",
|
|
7486
|
+
"a UUID string",
|
|
7487
|
+
"repair packageId in the authoring file",
|
|
7488
|
+
{ propertyPath, value }
|
|
7489
|
+
)
|
|
7490
|
+
);
|
|
7491
|
+
}
|
|
7492
|
+
const parsed = PackageId.parse(value);
|
|
7493
|
+
if (!parsed.ok) {
|
|
7494
|
+
return failure(
|
|
7495
|
+
authoringError(
|
|
7496
|
+
"pack-package-id-invalid",
|
|
7497
|
+
"a 36-character RFC 4122 UUID",
|
|
7498
|
+
"repair packageId or use the authoring gateway to mint one",
|
|
7499
|
+
{ propertyPath, value },
|
|
7500
|
+
value
|
|
7501
|
+
)
|
|
7502
|
+
);
|
|
7503
|
+
}
|
|
7504
|
+
return ok(parsed.value);
|
|
7505
|
+
}
|
|
7506
|
+
function parsePackJsonAsset(value, sourceKey) {
|
|
7507
|
+
if (!isRecord(value))
|
|
7508
|
+
return jsonError(
|
|
7509
|
+
`$.assets.${sourceKey}`,
|
|
7510
|
+
"an asset entry object",
|
|
7511
|
+
value,
|
|
7512
|
+
"asset entry is not an object"
|
|
7513
|
+
);
|
|
7514
|
+
const allowed = /* @__PURE__ */ new Set(["kind", "payload", "refs", "name", "artifacts"]);
|
|
7515
|
+
const unknown = Object.keys(value).find((key) => !allowed.has(key));
|
|
7516
|
+
if (unknown !== void 0)
|
|
7517
|
+
return jsonError(
|
|
7518
|
+
`$.assets.${sourceKey}.${unknown}`,
|
|
7519
|
+
"no GUID or extra authoring field",
|
|
7520
|
+
value[unknown],
|
|
7521
|
+
"direct v3 entries derive identity from their object key"
|
|
7522
|
+
);
|
|
7523
|
+
if (typeof value.kind !== "string" || value.kind.length === 0)
|
|
7524
|
+
return jsonError(
|
|
7525
|
+
`$.assets.${sourceKey}.kind`,
|
|
7526
|
+
"a non-empty asset kind",
|
|
7527
|
+
value.kind,
|
|
7528
|
+
"asset kind is missing"
|
|
7529
|
+
);
|
|
7530
|
+
if (!isRecord(value.payload))
|
|
7531
|
+
return jsonError(
|
|
7532
|
+
`$.assets.${sourceKey}.payload`,
|
|
7533
|
+
"a JSON object payload",
|
|
7534
|
+
value.payload,
|
|
7535
|
+
"payload must be a plain object"
|
|
7536
|
+
);
|
|
7537
|
+
if (!Array.isArray(value.refs) || value.refs.some((ref) => typeof ref !== "string" || !isValidAssetGuidString(ref))) {
|
|
7538
|
+
return jsonError(
|
|
7539
|
+
`$.assets.${sourceKey}.refs`,
|
|
7540
|
+
"an array of UUID references",
|
|
7541
|
+
value.refs,
|
|
7542
|
+
"references must already be real AssetGuids"
|
|
7543
|
+
);
|
|
7544
|
+
}
|
|
7545
|
+
if (value.name !== void 0 && (typeof value.name !== "string" || value.name.length === 0))
|
|
7546
|
+
return jsonError(
|
|
7547
|
+
`$.assets.${sourceKey}.name`,
|
|
7548
|
+
"a non-empty display name when present",
|
|
7549
|
+
value.name,
|
|
7550
|
+
"asset name is malformed"
|
|
7551
|
+
);
|
|
7552
|
+
if (value.artifacts !== void 0 && !isRecord(value.artifacts))
|
|
7553
|
+
return jsonError(
|
|
7554
|
+
`$.assets.${sourceKey}.artifacts`,
|
|
7555
|
+
"an artifact descriptor object when present",
|
|
7556
|
+
value.artifacts,
|
|
7557
|
+
"artifacts are not an object"
|
|
7558
|
+
);
|
|
7559
|
+
const base = {
|
|
7560
|
+
kind: value.kind,
|
|
7561
|
+
payload: value.payload,
|
|
7562
|
+
refs: Object.freeze([...value.refs]),
|
|
7563
|
+
...value.name === void 0 ? {} : { name: value.name }
|
|
7564
|
+
};
|
|
7565
|
+
if (value.artifacts === void 0) return ok(base);
|
|
7566
|
+
const withArtifacts = {
|
|
7567
|
+
...base,
|
|
7568
|
+
artifacts: value.artifacts
|
|
7569
|
+
};
|
|
7570
|
+
return ok(withArtifacts);
|
|
7571
|
+
}
|
|
7572
|
+
function parsePackSourceJson(value) {
|
|
7573
|
+
if (!isRecord(value))
|
|
7574
|
+
return jsonError("$", "a v3 pack.json object", value, "document is not an object");
|
|
7575
|
+
if (value.schemaVersion !== "3.0.0")
|
|
7576
|
+
return jsonError(
|
|
7577
|
+
"$.schemaVersion",
|
|
7578
|
+
"the literal '3.0.0'",
|
|
7579
|
+
value.schemaVersion,
|
|
7580
|
+
"document schema is not v3"
|
|
7581
|
+
);
|
|
7582
|
+
const unknown = Object.keys(value).find(
|
|
7583
|
+
(key) => !["schemaVersion", "packageId", "assets", "parent", "values"].includes(key)
|
|
7584
|
+
);
|
|
7585
|
+
if (unknown !== void 0)
|
|
7586
|
+
return jsonError(
|
|
7587
|
+
`$.${unknown}`,
|
|
7588
|
+
"no extra top-level authoring fields",
|
|
7589
|
+
value[unknown],
|
|
7590
|
+
"keep the v3 document to packageId+assets or packageId+parent+values"
|
|
7591
|
+
);
|
|
7592
|
+
const packageResult = parsePackageId(value.packageId, "$.packageId");
|
|
7593
|
+
if (!packageResult.ok) return packageResult;
|
|
7594
|
+
const hasAssets = Object.hasOwn(value, "assets");
|
|
7595
|
+
const hasParent = Object.hasOwn(value, "parent");
|
|
7596
|
+
const hasValues = Object.hasOwn(value, "values");
|
|
7597
|
+
if (hasAssets && (hasParent || hasValues))
|
|
7598
|
+
return jsonError(
|
|
7599
|
+
"$",
|
|
7600
|
+
"assets or parent+values, never both",
|
|
7601
|
+
value,
|
|
7602
|
+
"direct and instance branches are mutually exclusive"
|
|
7603
|
+
);
|
|
7604
|
+
if (hasAssets) {
|
|
7605
|
+
if (!isRecord(value.assets))
|
|
7606
|
+
return jsonError(
|
|
7607
|
+
"$.assets",
|
|
7608
|
+
"a sourceKey to asset object",
|
|
7609
|
+
value.assets,
|
|
7610
|
+
"direct assets are not an object"
|
|
7611
|
+
);
|
|
7612
|
+
const assets = {};
|
|
7613
|
+
for (const [sourceKey, entry] of Object.entries(value.assets)) {
|
|
7614
|
+
if (!isValidPackSourceKey(sourceKey))
|
|
7615
|
+
return failure(sourceKeyFailure(sourceKey, `$.assets.${sourceKey}`));
|
|
7616
|
+
const parsed = parsePackJsonAsset(entry, sourceKey);
|
|
7617
|
+
if (!parsed.ok) return parsed;
|
|
7618
|
+
assets[sourceKey] = parsed.value;
|
|
7619
|
+
}
|
|
7620
|
+
return ok({
|
|
7621
|
+
format: "direct",
|
|
7622
|
+
schemaVersion: "3.0.0",
|
|
7623
|
+
packageId: packageResult.value,
|
|
7624
|
+
assets: Object.freeze(assets)
|
|
7625
|
+
});
|
|
7626
|
+
}
|
|
7627
|
+
if (!hasParent || !hasValues || hasAssets)
|
|
7628
|
+
return jsonError(
|
|
7629
|
+
"$",
|
|
7630
|
+
"parent and values for an instance document",
|
|
7631
|
+
value,
|
|
7632
|
+
"instance branch is incomplete"
|
|
7633
|
+
);
|
|
7634
|
+
const parentResult = parsePackageId(value.parent, "$.parent");
|
|
7635
|
+
if (!parentResult.ok) return parentResult;
|
|
7636
|
+
if (!isRecord(value.values))
|
|
7637
|
+
return jsonError(
|
|
7638
|
+
"$.values",
|
|
7639
|
+
"a sparse parameter object",
|
|
7640
|
+
value.values,
|
|
7641
|
+
"instance values are not an object"
|
|
7642
|
+
);
|
|
7643
|
+
return ok({
|
|
7644
|
+
format: "instance",
|
|
7645
|
+
schemaVersion: "3.0.0",
|
|
7646
|
+
packageId: packageResult.value,
|
|
7647
|
+
parent: parentResult.value,
|
|
7648
|
+
values: Object.freeze({ ...value.values })
|
|
7649
|
+
});
|
|
7650
|
+
}
|
|
7651
|
+
function projectDirectPackJson(value) {
|
|
7652
|
+
const parsed = "format" in value ? ok(value) : parsePackSourceJson(value);
|
|
7653
|
+
if (!parsed.ok) return parsed;
|
|
7654
|
+
if (parsed.value.format !== "direct") {
|
|
7655
|
+
return failure(
|
|
7656
|
+
authoringError(
|
|
7657
|
+
"pack-parameter-invalid",
|
|
7658
|
+
"a direct v3 pack.json",
|
|
7659
|
+
"projectDirectPackJson accepts the direct branch only",
|
|
7660
|
+
{ observed: parsed.value.format }
|
|
7661
|
+
)
|
|
7662
|
+
);
|
|
7663
|
+
}
|
|
7664
|
+
const assets = [];
|
|
7665
|
+
for (const [sourceKey, entry] of Object.entries(parsed.value.assets).sort(
|
|
7666
|
+
([left], [right]) => left.localeCompare(right)
|
|
7667
|
+
)) {
|
|
7668
|
+
assets.push({
|
|
7669
|
+
...entry,
|
|
7670
|
+
guid: AssetGuid.format(AssetGuid.derive(parsed.value.packageId, sourceKey)),
|
|
7671
|
+
sourceKey
|
|
7672
|
+
});
|
|
7673
|
+
}
|
|
7674
|
+
return ok({ packageId: PackageId.format(parsed.value.packageId), assets: Object.freeze(assets) });
|
|
7675
|
+
}
|
|
7676
|
+
var PACK_AUTHORING_OPERATION_IDS = [
|
|
7677
|
+
"asset.list",
|
|
7678
|
+
"asset.inspect",
|
|
7679
|
+
"asset.resolve",
|
|
7680
|
+
"asset.verify",
|
|
7681
|
+
"asset-source.create",
|
|
7682
|
+
"asset-source.clone",
|
|
7683
|
+
"asset-source.create-instance",
|
|
7684
|
+
"asset-source.apply-values",
|
|
7685
|
+
"asset-source.rebuild",
|
|
7686
|
+
"asset-source.cold-cook"
|
|
7687
|
+
];
|
|
7688
|
+
PACK_AUTHORING_OPERATION_IDS.map((id) => ({
|
|
7689
|
+
id,
|
|
7690
|
+
domain: id.startsWith("asset-source.") ? "session" : "asset",
|
|
7691
|
+
readOnly: id.startsWith("asset."),
|
|
7692
|
+
requiresRevision: !id.startsWith("asset.") && id !== "asset-source.create"
|
|
7693
|
+
}));
|
|
7694
|
+
function isRecord2(value) {
|
|
6930
7695
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6931
7696
|
}
|
|
6932
7697
|
function hasText(value) {
|
|
6933
7698
|
return typeof value === "string" && value.length > 0;
|
|
6934
7699
|
}
|
|
6935
|
-
function issue(code, subjectId, expected, hint,
|
|
7700
|
+
function issue(code, subjectId, expected, hint, actual, authority = "producer") {
|
|
6936
7701
|
const subject = { type: "asset", id: subjectId };
|
|
6937
7702
|
return {
|
|
6938
7703
|
ok: false,
|
|
@@ -6940,7 +7705,7 @@ function issue(code, subjectId, expected, hint, actual2, authority = "producer")
|
|
|
6940
7705
|
code,
|
|
6941
7706
|
subject,
|
|
6942
7707
|
expected,
|
|
6943
|
-
...
|
|
7708
|
+
...actual === void 0 ? {} : { actual },
|
|
6944
7709
|
hint,
|
|
6945
7710
|
authority
|
|
6946
7711
|
}
|
|
@@ -6957,7 +7722,7 @@ function validateFacts(value, subjectId) {
|
|
|
6957
7722
|
}
|
|
6958
7723
|
if ("provenance" in value) {
|
|
6959
7724
|
const provenance = value.provenance;
|
|
6960
|
-
if (!
|
|
7725
|
+
if (!isRecord2(provenance) || !hasText(provenance.provider) || !hasText(provenance.version)) {
|
|
6961
7726
|
return issue(
|
|
6962
7727
|
"invalid-producer-fact",
|
|
6963
7728
|
subjectId,
|
|
@@ -6968,7 +7733,7 @@ function validateFacts(value, subjectId) {
|
|
|
6968
7733
|
}
|
|
6969
7734
|
if ("revision" in value) {
|
|
6970
7735
|
const revision = value.revision;
|
|
6971
|
-
if (!
|
|
7736
|
+
if (!isRecord2(revision) || !hasText(revision.digest) || !hasText(revision.rootId) || typeof revision.observedAt !== "number" || !Number.isFinite(revision.observedAt)) {
|
|
6972
7737
|
return issue(
|
|
6973
7738
|
"invalid-producer-fact",
|
|
6974
7739
|
subjectId,
|
|
@@ -6987,7 +7752,7 @@ function validateFacts(value, subjectId) {
|
|
|
6987
7752
|
);
|
|
6988
7753
|
}
|
|
6989
7754
|
for (const diagnostic of value.diagnostics) {
|
|
6990
|
-
if (!
|
|
7755
|
+
if (!isRecord2(diagnostic) || !hasText(diagnostic.code)) {
|
|
6991
7756
|
return issue(
|
|
6992
7757
|
"invalid-producer-fact",
|
|
6993
7758
|
subjectId,
|
|
@@ -6996,7 +7761,7 @@ function validateFacts(value, subjectId) {
|
|
|
6996
7761
|
);
|
|
6997
7762
|
}
|
|
6998
7763
|
if (diagnostic.severity === "blocking") {
|
|
6999
|
-
if (!
|
|
7764
|
+
if (!isRecord2(diagnostic.subject) || !hasText(diagnostic.subject.id)) {
|
|
7000
7765
|
return issue(
|
|
7001
7766
|
"invalid-producer-fact",
|
|
7002
7767
|
subjectId,
|
|
@@ -7020,7 +7785,7 @@ function validateFacts(value, subjectId) {
|
|
|
7020
7785
|
function validateMetaSourceOverrides(value, subjectId) {
|
|
7021
7786
|
if (!("sourceOverrides" in value)) return { ok: true, value };
|
|
7022
7787
|
const declaredSourceKeys = Array.isArray(value.subAssets) ? value.subAssets.flatMap(
|
|
7023
|
-
(subAsset) =>
|
|
7788
|
+
(subAsset) => isRecord2(subAsset) && hasText(subAsset.sourceKey) ? [subAsset.sourceKey] : []
|
|
7024
7789
|
) : [];
|
|
7025
7790
|
const result = validateSourceOverrideMap(value.sourceOverrides, declaredSourceKeys);
|
|
7026
7791
|
if (!result.ok) {
|
|
@@ -7039,7 +7804,7 @@ function validateMetaSourceOverrides(value, subjectId) {
|
|
|
7039
7804
|
};
|
|
7040
7805
|
}
|
|
7041
7806
|
function validateProducerContract(value) {
|
|
7042
|
-
if (!
|
|
7807
|
+
if (!isRecord2(value)) {
|
|
7043
7808
|
return issue(
|
|
7044
7809
|
"invalid-producer-fact",
|
|
7045
7810
|
"unknown",
|
|
@@ -7141,83 +7906,25 @@ function baseName(p) {
|
|
|
7141
7906
|
const idx = Math.max(trimmed.lastIndexOf("/"), trimmed.lastIndexOf("\\"));
|
|
7142
7907
|
return idx === -1 ? trimmed : trimmed.slice(idx + 1);
|
|
7143
7908
|
}
|
|
7144
|
-
function deriveAssetName(packagePath,
|
|
7909
|
+
function deriveAssetName(packagePath, _assetCount, storedName) {
|
|
7145
7910
|
if (packagePath === null) {
|
|
7146
7911
|
return "";
|
|
7147
7912
|
}
|
|
7148
|
-
|
|
7149
|
-
return baseName(packagePath);
|
|
7150
|
-
}
|
|
7913
|
+
return baseName(packagePath);
|
|
7151
7914
|
}
|
|
7152
7915
|
|
|
7153
7916
|
// src/resolve-asset-source.ts
|
|
7154
7917
|
function deriveSourceName(metaFileName) {
|
|
7155
7918
|
return metaFileName.replace(/\.meta\.json$/, "");
|
|
7156
7919
|
}
|
|
7157
|
-
|
|
7158
|
-
function isPathEscape(pathDir, resolved) {
|
|
7159
|
-
const rel = posix.relative(pathDir, resolved);
|
|
7160
|
-
return rel.startsWith("..") || posix.isAbsolute(rel);
|
|
7161
|
-
}
|
|
7162
|
-
function resolveAssetSource(metaPath, source, paths) {
|
|
7920
|
+
function resolveAssetSource(metaPath, source) {
|
|
7163
7921
|
if (source === void 0) {
|
|
7164
7922
|
const metaDir = dirname(metaPath);
|
|
7165
7923
|
const metaName = deriveAssetName(metaPath);
|
|
7166
7924
|
const derived = deriveSourceName(metaName);
|
|
7167
|
-
return
|
|
7925
|
+
return resolve(metaDir, derived);
|
|
7168
7926
|
}
|
|
7169
|
-
|
|
7170
|
-
const match = source.match(PATH_REF_RE);
|
|
7171
|
-
if (!match) {
|
|
7172
|
-
return err(
|
|
7173
|
-
new PackError({
|
|
7174
|
-
code: "pack-malformed-path-ref",
|
|
7175
|
-
expected: "source in format @<name>/<rest>",
|
|
7176
|
-
hint: PACK_ERROR_HINTS["pack-malformed-path-ref"],
|
|
7177
|
-
detail: {
|
|
7178
|
-
code: "pack-malformed-path-ref",
|
|
7179
|
-
reason: "format",
|
|
7180
|
-
rawSource: source,
|
|
7181
|
-
expectedFormat: "@<name>/<rest>"
|
|
7182
|
-
}
|
|
7183
|
-
})
|
|
7184
|
-
);
|
|
7185
|
-
}
|
|
7186
|
-
const [, name, rest] = match;
|
|
7187
|
-
const pathDir = paths[name];
|
|
7188
|
-
if (pathDir === void 0) {
|
|
7189
|
-
return err(
|
|
7190
|
-
new PackError({
|
|
7191
|
-
code: "pack-unknown-path",
|
|
7192
|
-
expected: "path name found in package.json#forgeax.assets.paths",
|
|
7193
|
-
hint: PACK_ERROR_HINTS["pack-unknown-path"],
|
|
7194
|
-
detail: {
|
|
7195
|
-
code: "pack-unknown-path",
|
|
7196
|
-
pathName: name,
|
|
7197
|
-
knownNames: Object.keys(paths)
|
|
7198
|
-
}
|
|
7199
|
-
})
|
|
7200
|
-
);
|
|
7201
|
-
}
|
|
7202
|
-
const resolved = resolve(pathDir, rest);
|
|
7203
|
-
if (isPathEscape(pathDir, resolved)) {
|
|
7204
|
-
return err(
|
|
7205
|
-
new PackError({
|
|
7206
|
-
code: "pack-malformed-path-ref",
|
|
7207
|
-
expected: "rest path must not escape the declared path directory",
|
|
7208
|
-
hint: PACK_ERROR_HINTS["pack-malformed-path-ref"],
|
|
7209
|
-
detail: {
|
|
7210
|
-
code: "pack-malformed-path-ref",
|
|
7211
|
-
reason: "escape",
|
|
7212
|
-
rawSource: source,
|
|
7213
|
-
expectedFormat: "@<name>/<rest>"
|
|
7214
|
-
}
|
|
7215
|
-
})
|
|
7216
|
-
);
|
|
7217
|
-
}
|
|
7218
|
-
return ok(resolved);
|
|
7219
|
-
}
|
|
7220
|
-
return ok(resolve(dirname(metaPath), source));
|
|
7927
|
+
return resolve(dirname(metaPath), source);
|
|
7221
7928
|
}
|
|
7222
7929
|
|
|
7223
7930
|
// src/schema-compiled.ts
|
|
@@ -7267,7 +7974,7 @@ var meta_schema_default = {
|
|
|
7267
7974
|
source: {
|
|
7268
7975
|
type: "string",
|
|
7269
7976
|
minLength: 1,
|
|
7270
|
-
description: "Optional. Omit to derive the companion file in the same directory (strip .meta.json suffix from the meta filename).
|
|
7977
|
+
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."
|
|
7271
7978
|
},
|
|
7272
7979
|
importSettings: {
|
|
7273
7980
|
type: "object",
|
|
@@ -7408,11 +8115,11 @@ var pack_schema_default = {
|
|
|
7408
8115
|
$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.",
|
|
7409
8116
|
type: "object",
|
|
7410
8117
|
additionalProperties: false,
|
|
7411
|
-
required: ["schemaVersion"
|
|
8118
|
+
required: ["schemaVersion"],
|
|
7412
8119
|
properties: {
|
|
7413
8120
|
schemaVersion: {
|
|
7414
8121
|
type: "string",
|
|
7415
|
-
enum: ["1.0.0", "2.0.0"]
|
|
8122
|
+
enum: ["1.0.0", "2.0.0", "3.0.0"]
|
|
7416
8123
|
},
|
|
7417
8124
|
kind: {
|
|
7418
8125
|
type: "string",
|
|
@@ -7434,12 +8141,58 @@ var pack_schema_default = {
|
|
|
7434
8141
|
items: { $ref: "#/$defs/diagnostic" }
|
|
7435
8142
|
},
|
|
7436
8143
|
assets: {
|
|
7437
|
-
|
|
7438
|
-
|
|
7439
|
-
|
|
7440
|
-
|
|
8144
|
+
oneOf: [
|
|
8145
|
+
{
|
|
8146
|
+
type: "array",
|
|
8147
|
+
items: { $ref: "#/$defs/asset" }
|
|
8148
|
+
},
|
|
8149
|
+
{ $ref: "#/$defs/authoringAssets" }
|
|
8150
|
+
]
|
|
8151
|
+
},
|
|
8152
|
+
parent: {
|
|
8153
|
+
$ref: "#/$defs/guid36",
|
|
8154
|
+
description: "Parent ScriptablePack packageId for one v3 instance; the source may declare Pack parameters."
|
|
8155
|
+
},
|
|
8156
|
+
values: {
|
|
8157
|
+
type: "object",
|
|
8158
|
+
additionalProperties: true,
|
|
8159
|
+
description: "Sparse shallow parameter overrides for one v3 instance."
|
|
7441
8160
|
}
|
|
7442
8161
|
},
|
|
8162
|
+
oneOf: [
|
|
8163
|
+
{
|
|
8164
|
+
required: ["kind", "assets"],
|
|
8165
|
+
properties: {
|
|
8166
|
+
schemaVersion: { enum: ["1.0.0", "2.0.0"] },
|
|
8167
|
+
kind: { const: "internal-text-package" },
|
|
8168
|
+
assets: { type: "array" },
|
|
8169
|
+
parent: false,
|
|
8170
|
+
values: false
|
|
8171
|
+
}
|
|
8172
|
+
},
|
|
8173
|
+
{
|
|
8174
|
+
required: ["packageId", "assets"],
|
|
8175
|
+
properties: {
|
|
8176
|
+
schemaVersion: { const: "3.0.0" },
|
|
8177
|
+
kind: false,
|
|
8178
|
+
packageId: { $ref: "#/$defs/guid36" },
|
|
8179
|
+
assets: { $ref: "#/$defs/authoringAssets" },
|
|
8180
|
+
parent: false,
|
|
8181
|
+
values: false
|
|
8182
|
+
}
|
|
8183
|
+
},
|
|
8184
|
+
{
|
|
8185
|
+
required: ["packageId", "parent", "values"],
|
|
8186
|
+
properties: {
|
|
8187
|
+
schemaVersion: { const: "3.0.0" },
|
|
8188
|
+
kind: false,
|
|
8189
|
+
packageId: { $ref: "#/$defs/guid36" },
|
|
8190
|
+
parent: { $ref: "#/$defs/guid36" },
|
|
8191
|
+
values: { type: "object" },
|
|
8192
|
+
assets: false
|
|
8193
|
+
}
|
|
8194
|
+
}
|
|
8195
|
+
],
|
|
7443
8196
|
allOf: [
|
|
7444
8197
|
{
|
|
7445
8198
|
if: {
|
|
@@ -7531,6 +8284,30 @@ var pack_schema_default = {
|
|
|
7531
8284
|
}
|
|
7532
8285
|
]
|
|
7533
8286
|
},
|
|
8287
|
+
authoringAssets: {
|
|
8288
|
+
type: "object",
|
|
8289
|
+
additionalProperties: false,
|
|
8290
|
+
patternProperties: {
|
|
8291
|
+
"^[a-z0-9][a-z0-9._-]*(/[a-z0-9][a-z0-9._-]*)*$": {
|
|
8292
|
+
$ref: "#/$defs/authoringAsset"
|
|
8293
|
+
}
|
|
8294
|
+
}
|
|
8295
|
+
},
|
|
8296
|
+
authoringAsset: {
|
|
8297
|
+
type: "object",
|
|
8298
|
+
additionalProperties: false,
|
|
8299
|
+
required: ["kind", "payload", "refs"],
|
|
8300
|
+
properties: {
|
|
8301
|
+
kind: { type: "string", minLength: 1 },
|
|
8302
|
+
name: { type: "string", minLength: 1 },
|
|
8303
|
+
payload: { type: "object" },
|
|
8304
|
+
refs: {
|
|
8305
|
+
type: "array",
|
|
8306
|
+
items: { $ref: "#/$defs/guid36" }
|
|
8307
|
+
},
|
|
8308
|
+
artifacts: { $ref: "#/$defs/artifacts" }
|
|
8309
|
+
}
|
|
8310
|
+
},
|
|
7534
8311
|
artifacts: {
|
|
7535
8312
|
type: "object",
|
|
7536
8313
|
additionalProperties: false,
|
|
@@ -7638,467 +8415,6 @@ var ajv = new import_ajv.default({ strict: true, allErrors: false });
|
|
|
7638
8415
|
(0, import_ajv_formats.default)(ajv, ["uuid"]);
|
|
7639
8416
|
var validateMeta = ajv.compile(meta_schema_default);
|
|
7640
8417
|
var validatePack = ajv.compile(pack_schema_default);
|
|
7641
|
-
var SCRIPTABLE_PACK_ASSET_KINDS = [
|
|
7642
|
-
"mesh",
|
|
7643
|
-
"material",
|
|
7644
|
-
"scene",
|
|
7645
|
-
"texture",
|
|
7646
|
-
"equirect",
|
|
7647
|
-
"sampler",
|
|
7648
|
-
"font",
|
|
7649
|
-
"render-pipeline",
|
|
7650
|
-
"tileset",
|
|
7651
|
-
"video",
|
|
7652
|
-
"skeleton",
|
|
7653
|
-
"skin",
|
|
7654
|
-
"animation-clip",
|
|
7655
|
-
"animation-graph",
|
|
7656
|
-
"audio",
|
|
7657
|
-
"particle-effect"
|
|
7658
|
-
];
|
|
7659
|
-
function isScriptablePackAssetKind(value) {
|
|
7660
|
-
return SCRIPTABLE_PACK_ASSET_KINDS.includes(value);
|
|
7661
|
-
}
|
|
7662
|
-
function sceneComponentFieldType(value) {
|
|
7663
|
-
if (typeof value === "string") return value;
|
|
7664
|
-
if (isRecord2(value) && typeof value.type === "string") return value.type;
|
|
7665
|
-
return void 0;
|
|
7666
|
-
}
|
|
7667
|
-
function projectScriptablePackSceneComponents(components) {
|
|
7668
|
-
return (components ?? []).map((component) => ({
|
|
7669
|
-
name: component.name,
|
|
7670
|
-
fields: Object.fromEntries(
|
|
7671
|
-
Object.entries(component.fields).map(([fieldName, field]) => [
|
|
7672
|
-
fieldName,
|
|
7673
|
-
sceneComponentFieldType(field)
|
|
7674
|
-
])
|
|
7675
|
-
)
|
|
7676
|
-
}));
|
|
7677
|
-
}
|
|
7678
|
-
var SCRIPTABLE_PACK_REQUEST_ID_SCHEMA = {
|
|
7679
|
-
type: "string",
|
|
7680
|
-
minLength: 1,
|
|
7681
|
-
maxLength: 128,
|
|
7682
|
-
pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$",
|
|
7683
|
-
description: "Caller-minted identity for one idempotent ScriptablePack operation."
|
|
7684
|
-
};
|
|
7685
|
-
var SCRIPTABLE_PACK_SOURCE_PATH_SCHEMA = {
|
|
7686
|
-
type: "string",
|
|
7687
|
-
minLength: 8,
|
|
7688
|
-
pattern: "^[^/].*\\.pack\\.ts$",
|
|
7689
|
-
description: "Game-root-relative ScriptablePack source path."
|
|
7690
|
-
};
|
|
7691
|
-
var SCRIPTABLE_PACK_OWNER_GUID_SCHEMA = {
|
|
7692
|
-
type: "string",
|
|
7693
|
-
format: "uuid",
|
|
7694
|
-
description: "Catalog GUID used to resolve the producer-owned source subject."
|
|
7695
|
-
};
|
|
7696
|
-
var SCRIPTABLE_PACK_REVISION_SCHEMA = {
|
|
7697
|
-
type: "string",
|
|
7698
|
-
minLength: 64,
|
|
7699
|
-
maxLength: 64,
|
|
7700
|
-
pattern: "^[a-f0-9]{64}$",
|
|
7701
|
-
description: "SHA-256 source revision returned by preflight."
|
|
7702
|
-
};
|
|
7703
|
-
var SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA = { type: "string", minLength: 1 };
|
|
7704
|
-
var SCRIPTABLE_PACK_ASSET_KIND_SCHEMA = {
|
|
7705
|
-
enum: SCRIPTABLE_PACK_ASSET_KINDS,
|
|
7706
|
-
description: "Ordinary Asset kind supported by the ScriptablePack producer/loader matrix."
|
|
7707
|
-
};
|
|
7708
|
-
var SCRIPTABLE_PACK_NAME_SCHEMA = { type: "string", minLength: 1 };
|
|
7709
|
-
function scriptablePackArgsSchema(properties, required, options = {}) {
|
|
7710
|
-
const subjectRequired = ["requestId", ...required];
|
|
7711
|
-
return {
|
|
7712
|
-
type: "object",
|
|
7713
|
-
properties: {
|
|
7714
|
-
sourcePath: SCRIPTABLE_PACK_SOURCE_PATH_SCHEMA,
|
|
7715
|
-
ownerGuid: SCRIPTABLE_PACK_OWNER_GUID_SCHEMA,
|
|
7716
|
-
requestId: SCRIPTABLE_PACK_REQUEST_ID_SCHEMA,
|
|
7717
|
-
...properties
|
|
7718
|
-
},
|
|
7719
|
-
required: subjectRequired,
|
|
7720
|
-
...options.subject === false ? {} : {
|
|
7721
|
-
anyOf: [
|
|
7722
|
-
{ required: [...subjectRequired, "sourcePath"] },
|
|
7723
|
-
{ required: [...subjectRequired, "ownerGuid"] },
|
|
7724
|
-
...options.guidSubject === false ? [] : [{ required: [...subjectRequired, "guid"] }]
|
|
7725
|
-
]
|
|
7726
|
-
},
|
|
7727
|
-
additionalProperties: false
|
|
7728
|
-
};
|
|
7729
|
-
}
|
|
7730
|
-
[
|
|
7731
|
-
{
|
|
7732
|
-
id: "asset-source.create",
|
|
7733
|
-
kind: "create",
|
|
7734
|
-
domain: "session",
|
|
7735
|
-
title: "Create Asset Source",
|
|
7736
|
-
argsSchema: scriptablePackArgsSchema(
|
|
7737
|
-
{
|
|
7738
|
-
name: SCRIPTABLE_PACK_NAME_SCHEMA,
|
|
7739
|
-
initialOutput: {
|
|
7740
|
-
type: "object",
|
|
7741
|
-
properties: {
|
|
7742
|
-
sourceKey: SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA,
|
|
7743
|
-
kind: SCRIPTABLE_PACK_ASSET_KIND_SCHEMA,
|
|
7744
|
-
name: SCRIPTABLE_PACK_NAME_SCHEMA
|
|
7745
|
-
},
|
|
7746
|
-
required: ["sourceKey", "kind"],
|
|
7747
|
-
additionalProperties: false
|
|
7748
|
-
}
|
|
7749
|
-
},
|
|
7750
|
-
["sourcePath", "initialOutput"],
|
|
7751
|
-
{ subject: false }
|
|
7752
|
-
)
|
|
7753
|
-
},
|
|
7754
|
-
{
|
|
7755
|
-
id: "asset-source.add-output",
|
|
7756
|
-
kind: "add-output",
|
|
7757
|
-
domain: "session",
|
|
7758
|
-
title: "Add Asset Source Output",
|
|
7759
|
-
argsSchema: scriptablePackArgsSchema(
|
|
7760
|
-
{
|
|
7761
|
-
sourceKey: SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA,
|
|
7762
|
-
assetKind: SCRIPTABLE_PACK_ASSET_KIND_SCHEMA,
|
|
7763
|
-
name: SCRIPTABLE_PACK_NAME_SCHEMA,
|
|
7764
|
-
expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA
|
|
7765
|
-
},
|
|
7766
|
-
["sourceKey", "assetKind", "expectedRevision"]
|
|
7767
|
-
)
|
|
7768
|
-
},
|
|
7769
|
-
{
|
|
7770
|
-
id: "asset-source.add-external-asset",
|
|
7771
|
-
kind: "add-external-asset",
|
|
7772
|
-
domain: "session",
|
|
7773
|
-
title: "Add Asset Source External Asset",
|
|
7774
|
-
argsSchema: scriptablePackArgsSchema(
|
|
7775
|
-
{
|
|
7776
|
-
alias: SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA,
|
|
7777
|
-
guid: { type: "string", format: "uuid" },
|
|
7778
|
-
expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA
|
|
7779
|
-
},
|
|
7780
|
-
["alias", "guid", "expectedRevision"],
|
|
7781
|
-
{ guidSubject: false }
|
|
7782
|
-
)
|
|
7783
|
-
},
|
|
7784
|
-
{
|
|
7785
|
-
id: "asset-source.rename",
|
|
7786
|
-
kind: "rename",
|
|
7787
|
-
domain: "session",
|
|
7788
|
-
title: "Rename Asset Source Display Name",
|
|
7789
|
-
argsSchema: scriptablePackArgsSchema(
|
|
7790
|
-
{
|
|
7791
|
-
target: {
|
|
7792
|
-
oneOf: [
|
|
7793
|
-
{
|
|
7794
|
-
type: "object",
|
|
7795
|
-
properties: { kind: { const: "package" } },
|
|
7796
|
-
required: ["kind"],
|
|
7797
|
-
additionalProperties: false
|
|
7798
|
-
},
|
|
7799
|
-
{
|
|
7800
|
-
type: "object",
|
|
7801
|
-
properties: {
|
|
7802
|
-
kind: { const: "output" },
|
|
7803
|
-
sourceKey: SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA
|
|
7804
|
-
},
|
|
7805
|
-
required: ["kind", "sourceKey"],
|
|
7806
|
-
additionalProperties: false
|
|
7807
|
-
}
|
|
7808
|
-
]
|
|
7809
|
-
},
|
|
7810
|
-
name: SCRIPTABLE_PACK_NAME_SCHEMA,
|
|
7811
|
-
expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA
|
|
7812
|
-
},
|
|
7813
|
-
["target", "name", "expectedRevision"]
|
|
7814
|
-
)
|
|
7815
|
-
},
|
|
7816
|
-
{
|
|
7817
|
-
id: "asset-source.remove-output",
|
|
7818
|
-
kind: "remove-output",
|
|
7819
|
-
domain: "session",
|
|
7820
|
-
title: "Remove Asset Source Output",
|
|
7821
|
-
destructive: true,
|
|
7822
|
-
argsSchema: scriptablePackArgsSchema(
|
|
7823
|
-
{
|
|
7824
|
-
sourceKey: SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA,
|
|
7825
|
-
confirmIncomingRefs: { type: "array", items: { type: "string" } },
|
|
7826
|
-
expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA
|
|
7827
|
-
},
|
|
7828
|
-
["sourceKey", "expectedRevision"]
|
|
7829
|
-
)
|
|
7830
|
-
},
|
|
7831
|
-
{
|
|
7832
|
-
id: "asset-source.clone",
|
|
7833
|
-
kind: "clone",
|
|
7834
|
-
domain: "session",
|
|
7835
|
-
title: "Clone Asset Source",
|
|
7836
|
-
argsSchema: scriptablePackArgsSchema(
|
|
7837
|
-
{
|
|
7838
|
-
targetPath: SCRIPTABLE_PACK_SOURCE_PATH_SCHEMA,
|
|
7839
|
-
expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA
|
|
7840
|
-
},
|
|
7841
|
-
["targetPath", "expectedRevision"]
|
|
7842
|
-
)
|
|
7843
|
-
},
|
|
7844
|
-
{
|
|
7845
|
-
id: "asset-source.rebuild",
|
|
7846
|
-
kind: "rebuild",
|
|
7847
|
-
domain: "session",
|
|
7848
|
-
title: "Rebuild Asset Source",
|
|
7849
|
-
argsSchema: scriptablePackArgsSchema({ expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA }, [
|
|
7850
|
-
"expectedRevision"
|
|
7851
|
-
])
|
|
7852
|
-
},
|
|
7853
|
-
{
|
|
7854
|
-
id: "asset-source.cold-cook",
|
|
7855
|
-
kind: "cold-cook",
|
|
7856
|
-
domain: "session",
|
|
7857
|
-
title: "Cold Cook Asset Source",
|
|
7858
|
-
argsSchema: scriptablePackArgsSchema({ expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA }, [
|
|
7859
|
-
"expectedRevision"
|
|
7860
|
-
])
|
|
7861
|
-
}
|
|
7862
|
-
];
|
|
7863
|
-
function actual(value) {
|
|
7864
|
-
if (value === null) return "null";
|
|
7865
|
-
if (Array.isArray(value)) return "array";
|
|
7866
|
-
if (ArrayBuffer.isView(value)) return value.constructor.name;
|
|
7867
|
-
return typeof value;
|
|
7868
|
-
}
|
|
7869
|
-
function invalid(propertyPath, expected, value, sourcePath) {
|
|
7870
|
-
return err({
|
|
7871
|
-
code: "pack-source-definition-invalid",
|
|
7872
|
-
expected,
|
|
7873
|
-
hint: "repair the default exported ScriptablePack definition, then inspect Meta again",
|
|
7874
|
-
detail: {
|
|
7875
|
-
...sourcePath === void 0 ? {} : { sourcePath },
|
|
7876
|
-
propertyPath,
|
|
7877
|
-
actual: actual(value)
|
|
7878
|
-
}
|
|
7879
|
-
});
|
|
7880
|
-
}
|
|
7881
|
-
function isRecord2(value) {
|
|
7882
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
7883
|
-
}
|
|
7884
|
-
function isAssetGuid(value) {
|
|
7885
|
-
return value instanceof Uint8Array && value.byteLength === 16;
|
|
7886
|
-
}
|
|
7887
|
-
function guidKey(guid) {
|
|
7888
|
-
return AssetGuid.format(guid);
|
|
7889
|
-
}
|
|
7890
|
-
function freezeDefinition(definition) {
|
|
7891
|
-
const assets = Object.fromEntries(
|
|
7892
|
-
Object.entries(definition.assets).map(([sourceKey, descriptor]) => [
|
|
7893
|
-
sourceKey,
|
|
7894
|
-
Object.freeze({ ...descriptor, guid: descriptor.guid.slice() })
|
|
7895
|
-
])
|
|
7896
|
-
);
|
|
7897
|
-
const externalAssets = Object.fromEntries(
|
|
7898
|
-
Object.entries(definition.externalAssets).map(([alias, guid]) => [
|
|
7899
|
-
alias,
|
|
7900
|
-
guid.slice()
|
|
7901
|
-
])
|
|
7902
|
-
);
|
|
7903
|
-
const sceneComponents = definition.sceneComponents === void 0 ? void 0 : Object.freeze(
|
|
7904
|
-
projectScriptablePackSceneComponents(definition.sceneComponents).map(
|
|
7905
|
-
(component) => Object.freeze({
|
|
7906
|
-
...component,
|
|
7907
|
-
fields: Object.freeze({ ...component.fields })
|
|
7908
|
-
})
|
|
7909
|
-
)
|
|
7910
|
-
);
|
|
7911
|
-
return Object.freeze({
|
|
7912
|
-
...definition,
|
|
7913
|
-
packageId: definition.packageId.slice(),
|
|
7914
|
-
assets: Object.freeze(assets),
|
|
7915
|
-
externalAssets: Object.freeze(externalAssets),
|
|
7916
|
-
...sceneComponents === void 0 ? {} : { sceneComponents }
|
|
7917
|
-
});
|
|
7918
|
-
}
|
|
7919
|
-
function validateScriptablePackDefinition(value, sourcePath) {
|
|
7920
|
-
if (!isRecord2(value))
|
|
7921
|
-
return invalid("$", "a ScriptablePack definition object", value, sourcePath);
|
|
7922
|
-
if (value.schemaVersion !== "1.0.0") {
|
|
7923
|
-
return invalid("$.schemaVersion", "the literal '1.0.0'", value.schemaVersion, sourcePath);
|
|
7924
|
-
}
|
|
7925
|
-
if (!isAssetGuid(value.packageId)) {
|
|
7926
|
-
return invalid("$.packageId", "a 16-byte AssetGuid", value.packageId, sourcePath);
|
|
7927
|
-
}
|
|
7928
|
-
if (value.name !== void 0 && typeof value.name !== "string") {
|
|
7929
|
-
return invalid("$.name", "a string when present", value.name, sourcePath);
|
|
7930
|
-
}
|
|
7931
|
-
if (!isRecord2(value.assets) || Object.keys(value.assets).length === 0) {
|
|
7932
|
-
return invalid(
|
|
7933
|
-
"$.assets",
|
|
7934
|
-
"a non-empty sourceKey to descriptor object",
|
|
7935
|
-
value.assets,
|
|
7936
|
-
sourcePath
|
|
7937
|
-
);
|
|
7938
|
-
}
|
|
7939
|
-
if (!isRecord2(value.externalAssets)) {
|
|
7940
|
-
return invalid(
|
|
7941
|
-
"$.externalAssets",
|
|
7942
|
-
"an alias to AssetGuid object",
|
|
7943
|
-
value.externalAssets,
|
|
7944
|
-
sourcePath
|
|
7945
|
-
);
|
|
7946
|
-
}
|
|
7947
|
-
if (value.sceneComponents !== void 0) {
|
|
7948
|
-
if (!Array.isArray(value.sceneComponents)) {
|
|
7949
|
-
return invalid(
|
|
7950
|
-
"$.sceneComponents",
|
|
7951
|
-
"an array of component tokens or neutral schema rows when present",
|
|
7952
|
-
value.sceneComponents,
|
|
7953
|
-
sourcePath
|
|
7954
|
-
);
|
|
7955
|
-
}
|
|
7956
|
-
const componentNames = /* @__PURE__ */ new Set();
|
|
7957
|
-
for (const [componentIndex, component] of value.sceneComponents.entries()) {
|
|
7958
|
-
if (!isRecord2(component)) {
|
|
7959
|
-
return invalid(
|
|
7960
|
-
`$.sceneComponents[${componentIndex}]`,
|
|
7961
|
-
"a component token or neutral schema row",
|
|
7962
|
-
component,
|
|
7963
|
-
sourcePath
|
|
7964
|
-
);
|
|
7965
|
-
}
|
|
7966
|
-
if (typeof component.name !== "string" || component.name.trim().length === 0) {
|
|
7967
|
-
return invalid(
|
|
7968
|
-
`$.sceneComponents[${componentIndex}].name`,
|
|
7969
|
-
"a non-empty component name",
|
|
7970
|
-
component.name,
|
|
7971
|
-
sourcePath
|
|
7972
|
-
);
|
|
7973
|
-
}
|
|
7974
|
-
if (componentNames.has(component.name)) {
|
|
7975
|
-
return invalid(
|
|
7976
|
-
`$.sceneComponents[${componentIndex}].name`,
|
|
7977
|
-
"component names to be unique within one ScriptablePack",
|
|
7978
|
-
component.name,
|
|
7979
|
-
sourcePath
|
|
7980
|
-
);
|
|
7981
|
-
}
|
|
7982
|
-
componentNames.add(component.name);
|
|
7983
|
-
if (!isRecord2(component.fields)) {
|
|
7984
|
-
return invalid(
|
|
7985
|
-
`$.sceneComponents[${componentIndex}].fields`,
|
|
7986
|
-
"a field-name to schema-type object",
|
|
7987
|
-
component.fields,
|
|
7988
|
-
sourcePath
|
|
7989
|
-
);
|
|
7990
|
-
}
|
|
7991
|
-
for (const [fieldName, field] of Object.entries(component.fields)) {
|
|
7992
|
-
const type = sceneComponentFieldType(field);
|
|
7993
|
-
if (fieldName.trim().length === 0 || type === void 0 || type.trim().length === 0) {
|
|
7994
|
-
return invalid(
|
|
7995
|
-
`$.sceneComponents[${componentIndex}].fields`,
|
|
7996
|
-
"field names with non-empty string schema types",
|
|
7997
|
-
field,
|
|
7998
|
-
sourcePath
|
|
7999
|
-
);
|
|
8000
|
-
}
|
|
8001
|
-
}
|
|
8002
|
-
}
|
|
8003
|
-
}
|
|
8004
|
-
if (typeof value.build !== "function") {
|
|
8005
|
-
return invalid("$.build", "a build(assetReader) function", value.build, sourcePath);
|
|
8006
|
-
}
|
|
8007
|
-
const packageGuid = guidKey(value.packageId);
|
|
8008
|
-
const localGuids = /* @__PURE__ */ new Set();
|
|
8009
|
-
for (const [sourceKey, descriptor] of Object.entries(value.assets)) {
|
|
8010
|
-
if (sourceKey.trim().length === 0) {
|
|
8011
|
-
return invalid("$.assets", "non-empty sourceKey object keys", sourceKey, sourcePath);
|
|
8012
|
-
}
|
|
8013
|
-
if (!isRecord2(descriptor)) {
|
|
8014
|
-
return invalid(
|
|
8015
|
-
`$.assets[${JSON.stringify(sourceKey)}]`,
|
|
8016
|
-
"an asset descriptor",
|
|
8017
|
-
descriptor,
|
|
8018
|
-
sourcePath
|
|
8019
|
-
);
|
|
8020
|
-
}
|
|
8021
|
-
if (!isAssetGuid(descriptor.guid)) {
|
|
8022
|
-
return invalid(
|
|
8023
|
-
`$.assets[${JSON.stringify(sourceKey)}].guid`,
|
|
8024
|
-
"a 16-byte AssetGuid",
|
|
8025
|
-
descriptor.guid,
|
|
8026
|
-
sourcePath
|
|
8027
|
-
);
|
|
8028
|
-
}
|
|
8029
|
-
if (typeof descriptor.kind !== "string" || !isScriptablePackAssetKind(descriptor.kind)) {
|
|
8030
|
-
return invalid(
|
|
8031
|
-
`$.assets[${JSON.stringify(sourceKey)}].kind`,
|
|
8032
|
-
"one of SCRIPTABLE_PACK_ASSET_KINDS",
|
|
8033
|
-
descriptor.kind,
|
|
8034
|
-
sourcePath
|
|
8035
|
-
);
|
|
8036
|
-
}
|
|
8037
|
-
if (descriptor.name !== void 0 && typeof descriptor.name !== "string") {
|
|
8038
|
-
return invalid(
|
|
8039
|
-
`$.assets[${JSON.stringify(sourceKey)}].name`,
|
|
8040
|
-
"a string when present",
|
|
8041
|
-
descriptor.name,
|
|
8042
|
-
sourcePath
|
|
8043
|
-
);
|
|
8044
|
-
}
|
|
8045
|
-
const guid = guidKey(descriptor.guid);
|
|
8046
|
-
if (guid === packageGuid || localGuids.has(guid)) {
|
|
8047
|
-
return invalid(
|
|
8048
|
-
`$.assets[${JSON.stringify(sourceKey)}].guid`,
|
|
8049
|
-
"a GUID unique within the package and distinct from packageId",
|
|
8050
|
-
descriptor.guid,
|
|
8051
|
-
sourcePath
|
|
8052
|
-
);
|
|
8053
|
-
}
|
|
8054
|
-
localGuids.add(guid);
|
|
8055
|
-
}
|
|
8056
|
-
const externalGuids = /* @__PURE__ */ new Set();
|
|
8057
|
-
for (const [alias, guidValue] of Object.entries(value.externalAssets)) {
|
|
8058
|
-
if (alias.trim().length === 0) {
|
|
8059
|
-
return invalid("$.externalAssets", "non-empty alias object keys", alias, sourcePath);
|
|
8060
|
-
}
|
|
8061
|
-
if (!isAssetGuid(guidValue)) {
|
|
8062
|
-
return invalid(
|
|
8063
|
-
`$.externalAssets[${JSON.stringify(alias)}]`,
|
|
8064
|
-
"a 16-byte AssetGuid",
|
|
8065
|
-
guidValue,
|
|
8066
|
-
sourcePath
|
|
8067
|
-
);
|
|
8068
|
-
}
|
|
8069
|
-
const guid = guidKey(guidValue);
|
|
8070
|
-
if (guid === packageGuid || localGuids.has(guid) || externalGuids.has(guid)) {
|
|
8071
|
-
return invalid(
|
|
8072
|
-
`$.externalAssets[${JSON.stringify(alias)}]`,
|
|
8073
|
-
"a unique foreign GUID not owned by this package",
|
|
8074
|
-
guidValue,
|
|
8075
|
-
sourcePath
|
|
8076
|
-
);
|
|
8077
|
-
}
|
|
8078
|
-
externalGuids.add(guid);
|
|
8079
|
-
}
|
|
8080
|
-
return ok(freezeDefinition(value));
|
|
8081
|
-
}
|
|
8082
|
-
function projectScriptablePackMeta(definition, source) {
|
|
8083
|
-
const subAssets = Object.entries(definition.assets).sort(([left], [right]) => left.localeCompare(right)).map(([sourceKey, descriptor], sourceIndex) => ({
|
|
8084
|
-
guid: guidKey(descriptor.guid),
|
|
8085
|
-
sourceIndex,
|
|
8086
|
-
sourceKey,
|
|
8087
|
-
kind: descriptor.kind,
|
|
8088
|
-
...descriptor.name === void 0 ? {} : { name: descriptor.name }
|
|
8089
|
-
}));
|
|
8090
|
-
const externalAssets = Object.entries(definition.externalAssets).sort(([left], [right]) => left.localeCompare(right)).map(([alias, guid]) => ({ alias, guid: guidKey(guid) }));
|
|
8091
|
-
return {
|
|
8092
|
-
schemaVersion: "1.0.0",
|
|
8093
|
-
kind: "external-asset-package",
|
|
8094
|
-
packageId: guidKey(definition.packageId),
|
|
8095
|
-
...definition.name === void 0 ? {} : { name: definition.name },
|
|
8096
|
-
importer: "pack-ts",
|
|
8097
|
-
source,
|
|
8098
|
-
importSettings: { contractVersion: "1.0.0", externalAssets },
|
|
8099
|
-
subAssets
|
|
8100
|
-
};
|
|
8101
|
-
}
|
|
8102
8418
|
var IMPORT_META_RESOLVE_FLAG = "--experimental-import-meta-resolve";
|
|
8103
8419
|
function scriptablePackWorkerExecArgv() {
|
|
8104
8420
|
const inherited = process.execArgv.filter((arg) => !arg.startsWith("--input-type"));
|
|
@@ -8146,50 +8462,51 @@ async function inventoryScriptablePackSource(sourcePath, initialSourceText) {
|
|
|
8146
8462
|
}
|
|
8147
8463
|
function serializeFailure(value) {
|
|
8148
8464
|
if (value !== null && typeof value === "object") {
|
|
8149
|
-
const
|
|
8465
|
+
const failure2 = value;
|
|
8150
8466
|
return {
|
|
8151
|
-
name:
|
|
8152
|
-
code:
|
|
8153
|
-
expected:
|
|
8154
|
-
actual:
|
|
8155
|
-
hint:
|
|
8156
|
-
detail:
|
|
8157
|
-
message:
|
|
8467
|
+
name: failure2.name,
|
|
8468
|
+
code: failure2.code,
|
|
8469
|
+
expected: failure2.expected,
|
|
8470
|
+
actual: failure2.actual,
|
|
8471
|
+
hint: failure2.hint,
|
|
8472
|
+
detail: failure2.detail,
|
|
8473
|
+
message: failure2.message
|
|
8158
8474
|
};
|
|
8159
8475
|
}
|
|
8160
8476
|
return { message: String(value) };
|
|
8161
8477
|
}
|
|
8162
8478
|
function hydrateFailure(value) {
|
|
8163
8479
|
if (value === null || typeof value !== "object") return value;
|
|
8164
|
-
const
|
|
8165
|
-
if (
|
|
8480
|
+
const failure2 = value;
|
|
8481
|
+
if (failure2.name === "AssetError" && typeof failure2.code === "string" && typeof failure2.expected === "string" && typeof failure2.hint === "string") {
|
|
8166
8482
|
const args = {
|
|
8167
|
-
code:
|
|
8168
|
-
expected:
|
|
8169
|
-
hint:
|
|
8483
|
+
code: failure2.code,
|
|
8484
|
+
expected: failure2.expected,
|
|
8485
|
+
hint: failure2.hint
|
|
8170
8486
|
};
|
|
8171
|
-
return
|
|
8487
|
+
return failure2.detail === void 0 ? new AssetError(args) : new AssetError({
|
|
8172
8488
|
...args,
|
|
8173
|
-
detail:
|
|
8489
|
+
detail: failure2.detail
|
|
8174
8490
|
});
|
|
8175
8491
|
}
|
|
8176
|
-
if (
|
|
8492
|
+
if (failure2.name === "ImportError" && typeof failure2.code === "string" && typeof failure2.expected === "string" && typeof failure2.hint === "string" && failure2.detail !== void 0) {
|
|
8177
8493
|
return new ImportError({
|
|
8178
|
-
code:
|
|
8179
|
-
expected:
|
|
8180
|
-
hint:
|
|
8181
|
-
detail:
|
|
8182
|
-
...typeof
|
|
8494
|
+
code: failure2.code,
|
|
8495
|
+
expected: failure2.expected,
|
|
8496
|
+
hint: failure2.hint,
|
|
8497
|
+
detail: failure2.detail,
|
|
8498
|
+
...typeof failure2.actual === "string" ? { actual: failure2.actual } : {}
|
|
8183
8499
|
});
|
|
8184
8500
|
}
|
|
8185
|
-
if (typeof
|
|
8186
|
-
const error = new Error(
|
|
8187
|
-
if (typeof
|
|
8501
|
+
if (typeof failure2.message === "string") {
|
|
8502
|
+
const error = new Error(failure2.message);
|
|
8503
|
+
if (typeof failure2.name === "string") error.name = failure2.name;
|
|
8188
8504
|
return error;
|
|
8189
8505
|
}
|
|
8190
8506
|
return value;
|
|
8191
8507
|
}
|
|
8192
8508
|
var WorkerScriptablePackExecutor = class {
|
|
8509
|
+
supportsPackParameters = true;
|
|
8193
8510
|
worker;
|
|
8194
8511
|
compileRoot;
|
|
8195
8512
|
nextBuildId = 0;
|
|
@@ -8217,7 +8534,7 @@ var WorkerScriptablePackExecutor = class {
|
|
|
8217
8534
|
resolveLoad({
|
|
8218
8535
|
default: value.definition === void 0 ? void 0 : {
|
|
8219
8536
|
...value.definition,
|
|
8220
|
-
build: (
|
|
8537
|
+
build: (readByGuid, context) => this.runBuild({ readByGuid }, context)
|
|
8221
8538
|
}
|
|
8222
8539
|
});
|
|
8223
8540
|
} else if (value.kind === "load-threw") {
|
|
@@ -8249,7 +8566,7 @@ var WorkerScriptablePackExecutor = class {
|
|
|
8249
8566
|
})();
|
|
8250
8567
|
return this.disposal;
|
|
8251
8568
|
}
|
|
8252
|
-
runBuild(reader) {
|
|
8569
|
+
runBuild(reader, context) {
|
|
8253
8570
|
const worker = this.worker;
|
|
8254
8571
|
if (worker === void 0) return Promise.reject(new Error("ScriptablePack worker is closed"));
|
|
8255
8572
|
if (this.build !== void 0)
|
|
@@ -8257,7 +8574,7 @@ var WorkerScriptablePackExecutor = class {
|
|
|
8257
8574
|
const id = this.nextBuildId++;
|
|
8258
8575
|
return new Promise((resolveBuild, rejectBuild) => {
|
|
8259
8576
|
this.build = { id, reader, resolve: resolveBuild, reject: rejectBuild };
|
|
8260
|
-
worker.postMessage({ kind: "build", buildId: id });
|
|
8577
|
+
worker.postMessage({ kind: "build", buildId: id, context });
|
|
8261
8578
|
});
|
|
8262
8579
|
}
|
|
8263
8580
|
onMessage(message) {
|
|
@@ -8290,11 +8607,11 @@ function scriptablePackWorkerUrl() {
|
|
|
8290
8607
|
const bundledWorker = new URL("./scriptable-pack-worker.mjs", import.meta.url);
|
|
8291
8608
|
return existsSync(fileURLToPath(bundledWorker)) ? bundledWorker : new URL("../dist/scriptable-pack-worker.mjs", import.meta.url);
|
|
8292
8609
|
}
|
|
8293
|
-
function
|
|
8294
|
-
return
|
|
8295
|
-
code: "pack-
|
|
8296
|
-
expected: "a trusted
|
|
8297
|
-
hint: "repair the module
|
|
8610
|
+
function scriptablePackLoadFailure(sourcePath, reason, phase, diagnostic, timeoutMs) {
|
|
8611
|
+
return {
|
|
8612
|
+
code: "pack-parameter-invalid",
|
|
8613
|
+
expected: "a trusted Pack v2 authoring module with a valid default export",
|
|
8614
|
+
hint: "repair the source module or its build timeout, then inspect the Pack again",
|
|
8298
8615
|
detail: {
|
|
8299
8616
|
sourcePath,
|
|
8300
8617
|
reason,
|
|
@@ -8302,20 +8619,6 @@ function loadFailure(sourcePath, reason, phase, diagnostic, timeoutMs) {
|
|
|
8302
8619
|
diagnostic,
|
|
8303
8620
|
...timeoutMs === void 0 ? {} : { timeoutMs }
|
|
8304
8621
|
}
|
|
8305
|
-
});
|
|
8306
|
-
}
|
|
8307
|
-
function buildTimeoutFailure(sourcePath, timeoutMs) {
|
|
8308
|
-
return {
|
|
8309
|
-
code: "pack-source-load-failed",
|
|
8310
|
-
expected: "a ScriptablePack build to settle within the configured build timeout",
|
|
8311
|
-
hint: "repair the authored build, then retry through a fresh ScriptablePack generation",
|
|
8312
|
-
detail: {
|
|
8313
|
-
sourcePath,
|
|
8314
|
-
reason: "timeout",
|
|
8315
|
-
phase: "build",
|
|
8316
|
-
timeoutMs,
|
|
8317
|
-
diagnostic: `ScriptablePack build exceeded ${timeoutMs}ms`
|
|
8318
|
-
}
|
|
8319
8622
|
};
|
|
8320
8623
|
}
|
|
8321
8624
|
async function loadScriptablePack(sourcePath, options = {}) {
|
|
@@ -8334,34 +8637,49 @@ async function loadScriptablePack(sourcePath, options = {}) {
|
|
|
8334
8637
|
]);
|
|
8335
8638
|
if (loaded === timeoutSignal) {
|
|
8336
8639
|
disposeReason = "timeout";
|
|
8337
|
-
return
|
|
8338
|
-
|
|
8339
|
-
|
|
8340
|
-
|
|
8341
|
-
|
|
8342
|
-
|
|
8640
|
+
return err(
|
|
8641
|
+
scriptablePackLoadFailure(
|
|
8642
|
+
sourcePath,
|
|
8643
|
+
"timeout",
|
|
8644
|
+
"module-load",
|
|
8645
|
+
`Pack module initialization exceeded ${timeoutMs}ms`,
|
|
8646
|
+
timeoutMs
|
|
8647
|
+
)
|
|
8343
8648
|
);
|
|
8344
8649
|
}
|
|
8345
8650
|
const moduleValue = loaded !== null && typeof loaded === "object" && "default" in loaded ? loaded.default : void 0;
|
|
8346
|
-
const validated =
|
|
8651
|
+
const validated = validatePackDefinition(moduleValue, sourcePath);
|
|
8347
8652
|
if (!validated.ok) {
|
|
8348
8653
|
disposeReason = "failure";
|
|
8349
8654
|
return validated;
|
|
8350
8655
|
}
|
|
8351
8656
|
if (options.metadataOnly === true) {
|
|
8352
8657
|
disposeReason = "complete";
|
|
8353
|
-
return validated;
|
|
8658
|
+
return ok(validated.value);
|
|
8354
8659
|
}
|
|
8355
8660
|
const definition = validated.value;
|
|
8661
|
+
const build = definition.build;
|
|
8356
8662
|
return ok({
|
|
8357
8663
|
...definition,
|
|
8358
|
-
build: async (
|
|
8664
|
+
build: async (context) => {
|
|
8359
8665
|
let buildTimedOut = false;
|
|
8360
8666
|
let buildTimeout;
|
|
8361
|
-
const timeoutResult = err(
|
|
8667
|
+
const timeoutResult = err(
|
|
8668
|
+
scriptablePackLoadFailure(
|
|
8669
|
+
sourcePath,
|
|
8670
|
+
"timeout",
|
|
8671
|
+
"build",
|
|
8672
|
+
`ScriptablePack build exceeded ${buildTimeoutMs}ms`,
|
|
8673
|
+
buildTimeoutMs
|
|
8674
|
+
)
|
|
8675
|
+
);
|
|
8362
8676
|
try {
|
|
8677
|
+
const invocation = "supportsPackParameters" in executor && executor.supportsPackParameters === true ? build(context.readByGuid, {
|
|
8678
|
+
packageId: [...context.packageId],
|
|
8679
|
+
..."values" in context && context.values !== void 0 ? { values: context.values } : {}
|
|
8680
|
+
}) : definition.build(context);
|
|
8363
8681
|
const built = await Promise.race([
|
|
8364
|
-
Promise.resolve(
|
|
8682
|
+
Promise.resolve(invocation),
|
|
8365
8683
|
new Promise((resolve3) => {
|
|
8366
8684
|
buildTimeout = setTimeout(() => {
|
|
8367
8685
|
buildTimedOut = true;
|
|
@@ -8384,9 +8702,15 @@ async function loadScriptablePack(sourcePath, options = {}) {
|
|
|
8384
8702
|
}
|
|
8385
8703
|
});
|
|
8386
8704
|
} catch (error) {
|
|
8387
|
-
const diagnostic = error instanceof Error ? error.message : String(error);
|
|
8388
8705
|
disposeReason = "failure";
|
|
8389
|
-
return
|
|
8706
|
+
return err(
|
|
8707
|
+
scriptablePackLoadFailure(
|
|
8708
|
+
sourcePath,
|
|
8709
|
+
"module-load",
|
|
8710
|
+
"module-load",
|
|
8711
|
+
error instanceof Error ? error.message : String(error)
|
|
8712
|
+
)
|
|
8713
|
+
);
|
|
8390
8714
|
} finally {
|
|
8391
8715
|
if (timeout !== void 0) clearTimeout(timeout);
|
|
8392
8716
|
if (disposeReason !== void 0) await executor.dispose?.(disposeReason);
|
|
@@ -8400,11 +8724,15 @@ function ok3(value) {
|
|
|
8400
8724
|
function packErr(error) {
|
|
8401
8725
|
return { ok: false, error };
|
|
8402
8726
|
}
|
|
8727
|
+
function record(value) {
|
|
8728
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
8729
|
+
}
|
|
8403
8730
|
var STANDARD_SCRIPTABLE_PACK_SCAN_OPTIONS = Object.freeze(
|
|
8404
8731
|
{}
|
|
8405
8732
|
);
|
|
8406
8733
|
var BLACKLIST = /* @__PURE__ */ new Set([
|
|
8407
8734
|
"node_modules",
|
|
8735
|
+
"__tests__",
|
|
8408
8736
|
".forgeax-harness",
|
|
8409
8737
|
".forgeax",
|
|
8410
8738
|
".git",
|
|
@@ -8508,10 +8836,87 @@ async function scanValidated(roots, opts = {}, capture) {
|
|
|
8508
8836
|
const scriptablePaths = rawPaths.filter((p) => p.endsWith(".pack.ts"));
|
|
8509
8837
|
const guidToPath = /* @__PURE__ */ new Map();
|
|
8510
8838
|
const packRefs = /* @__PURE__ */ new Map();
|
|
8839
|
+
const packageIdToPath = /* @__PURE__ */ new Map();
|
|
8840
|
+
const packageKind = /* @__PURE__ */ new Map();
|
|
8841
|
+
const instanceParents = [];
|
|
8842
|
+
function registerPackage(packageId2, path, kind) {
|
|
8843
|
+
if (packageId2 === void 0) return void 0;
|
|
8844
|
+
const normalized = packageId2.toLowerCase();
|
|
8845
|
+
const existing = packageIdToPath.get(normalized);
|
|
8846
|
+
if (existing !== void 0) {
|
|
8847
|
+
return makePackError("pack-guid-collision", {
|
|
8848
|
+
paths: [existing, path],
|
|
8849
|
+
guid: normalized
|
|
8850
|
+
});
|
|
8851
|
+
}
|
|
8852
|
+
packageIdToPath.set(normalized, path);
|
|
8853
|
+
packageKind.set(normalized, kind);
|
|
8854
|
+
return void 0;
|
|
8855
|
+
}
|
|
8511
8856
|
for (const packPath of packPaths) {
|
|
8512
8857
|
const loaded = await readValidatedJson(packPath, "pack-malformed-pack", validatePack);
|
|
8513
8858
|
if (!loaded.ok) return loaded;
|
|
8514
8859
|
const { raw, parsed } = loaded.value;
|
|
8860
|
+
if (record(parsed) && parsed.schemaVersion === "3.0.0") {
|
|
8861
|
+
const authoring = parsePackSourceJson(parsed);
|
|
8862
|
+
if (!authoring.ok) {
|
|
8863
|
+
return packErr(
|
|
8864
|
+
makePackError("pack-malformed-pack", {
|
|
8865
|
+
path: packPath,
|
|
8866
|
+
ajvErrors: [{ instancePath: "", message: authoring.error.code }]
|
|
8867
|
+
})
|
|
8868
|
+
);
|
|
8869
|
+
}
|
|
8870
|
+
const packageId2 = authoring.value.packageId;
|
|
8871
|
+
const packageCollision2 = registerPackage(
|
|
8872
|
+
PackageId.format(packageId2),
|
|
8873
|
+
packPath,
|
|
8874
|
+
authoring.value.format
|
|
8875
|
+
);
|
|
8876
|
+
if (packageCollision2 !== void 0) return packErr(packageCollision2);
|
|
8877
|
+
if (authoring.value.format === "instance") {
|
|
8878
|
+
instanceParents.push({
|
|
8879
|
+
path: packPath,
|
|
8880
|
+
packageId: PackageId.format(authoring.value.packageId),
|
|
8881
|
+
parent: PackageId.format(authoring.value.parent)
|
|
8882
|
+
});
|
|
8883
|
+
} else {
|
|
8884
|
+
const projected = projectDirectPackJson(authoring.value);
|
|
8885
|
+
if (!projected.ok) {
|
|
8886
|
+
return packErr(
|
|
8887
|
+
makePackError("pack-malformed-pack", {
|
|
8888
|
+
path: packPath,
|
|
8889
|
+
ajvErrors: [{ instancePath: "/assets", message: projected.error.code }]
|
|
8890
|
+
})
|
|
8891
|
+
);
|
|
8892
|
+
}
|
|
8893
|
+
for (const asset of projected.value.assets) {
|
|
8894
|
+
const normalizedGuid = asset.guid.toLowerCase();
|
|
8895
|
+
const existing = guidToPath.get(normalizedGuid);
|
|
8896
|
+
if (existing !== void 0) {
|
|
8897
|
+
return packErr(
|
|
8898
|
+
makePackError("pack-guid-collision", {
|
|
8899
|
+
paths: [existing, packPath],
|
|
8900
|
+
guid: normalizedGuid
|
|
8901
|
+
})
|
|
8902
|
+
);
|
|
8903
|
+
}
|
|
8904
|
+
guidToPath.set(normalizedGuid, packPath);
|
|
8905
|
+
packRefs.set(normalizedGuid, [
|
|
8906
|
+
...asset.refs.map((ref) => ref.toLowerCase()),
|
|
8907
|
+
...extractMountSourceGuids(asset)
|
|
8908
|
+
]);
|
|
8909
|
+
}
|
|
8910
|
+
}
|
|
8911
|
+
capture?.declarations.set(packPath, {
|
|
8912
|
+
format: "pack.json",
|
|
8913
|
+
sourcePath: packPath,
|
|
8914
|
+
sourceRevision: `sha256:${createHash("sha256").update(raw).digest("hex")}`,
|
|
8915
|
+
sourceText: raw,
|
|
8916
|
+
value: parsed
|
|
8917
|
+
});
|
|
8918
|
+
continue;
|
|
8919
|
+
}
|
|
8515
8920
|
const packageContract = validateProducerContract(parsed);
|
|
8516
8921
|
if (!packageContract.ok) {
|
|
8517
8922
|
return packErr(
|
|
@@ -8522,6 +8927,8 @@ async function scanValidated(roots, opts = {}, capture) {
|
|
|
8522
8927
|
);
|
|
8523
8928
|
}
|
|
8524
8929
|
const packObj = parsed;
|
|
8930
|
+
const packageCollision = registerPackage(packObj.packageId, packPath, "legacy");
|
|
8931
|
+
if (packageCollision !== void 0) return packErr(packageCollision);
|
|
8525
8932
|
for (const asset of packObj.assets) {
|
|
8526
8933
|
if (asset.kind === "particle-effect" && asset.execution === "direct" && (asset.refs.length > 0 || Object.keys(asset.artifacts ?? {}).length > 0)) {
|
|
8527
8934
|
return packErr(
|
|
@@ -8612,7 +9019,6 @@ async function scanValidated(roots, opts = {}, capture) {
|
|
|
8612
9019
|
value: packObj
|
|
8613
9020
|
});
|
|
8614
9021
|
}
|
|
8615
|
-
const { paths: assetPaths } = loadAssetConfig(process.cwd());
|
|
8616
9022
|
for (const metaPath of metaPaths) {
|
|
8617
9023
|
const loaded = await readValidatedJson(metaPath, "pack-malformed-meta", validateMeta);
|
|
8618
9024
|
if (!loaded.ok) return loaded;
|
|
@@ -8627,6 +9033,8 @@ async function scanValidated(roots, opts = {}, capture) {
|
|
|
8627
9033
|
);
|
|
8628
9034
|
}
|
|
8629
9035
|
const metaObj = parsed;
|
|
9036
|
+
const packageCollision = registerPackage(metaObj.packageId, metaPath, "legacy");
|
|
9037
|
+
if (packageCollision !== void 0) return packErr(packageCollision);
|
|
8630
9038
|
capture?.declarations.set(metaPath, {
|
|
8631
9039
|
format: "meta.json",
|
|
8632
9040
|
sourcePath: metaPath,
|
|
@@ -8666,11 +9074,7 @@ async function scanValidated(roots, opts = {}, capture) {
|
|
|
8666
9074
|
);
|
|
8667
9075
|
}
|
|
8668
9076
|
}
|
|
8669
|
-
const
|
|
8670
|
-
if (!sourceResolved.ok) {
|
|
8671
|
-
return packErr(sourceResolved.error);
|
|
8672
|
-
}
|
|
8673
|
-
const expectedSourcePath = sourceResolved.value;
|
|
9077
|
+
const expectedSourcePath = resolveAssetSource(metaPath, metaObj.source);
|
|
8674
9078
|
try {
|
|
8675
9079
|
await stat(expectedSourcePath);
|
|
8676
9080
|
} catch {
|
|
@@ -8690,23 +9094,24 @@ async function scanValidated(roots, opts = {}, capture) {
|
|
|
8690
9094
|
return packErr(
|
|
8691
9095
|
makePackError("pack-malformed-meta", {
|
|
8692
9096
|
path: sourcePath,
|
|
8693
|
-
ajvErrors: [{ instancePath: "", message: "
|
|
9097
|
+
ajvErrors: [{ instancePath: "", message: "Pack source read failed" }]
|
|
8694
9098
|
})
|
|
8695
9099
|
);
|
|
8696
9100
|
}
|
|
8697
|
-
const
|
|
9101
|
+
const loaderOptions = {
|
|
8698
9102
|
...opts.scriptablePack ?? {},
|
|
8699
9103
|
...capture === void 0 ? { metadataOnly: true } : {}
|
|
8700
|
-
}
|
|
9104
|
+
};
|
|
9105
|
+
const loaded = await loadScriptablePack(sourcePath, loaderOptions);
|
|
8701
9106
|
if (!loaded.ok) {
|
|
8702
|
-
const diagnostic =
|
|
9107
|
+
const diagnostic = loaded.error.detail.diagnostic;
|
|
8703
9108
|
return packErr(
|
|
8704
9109
|
makePackError("pack-malformed-meta", {
|
|
8705
9110
|
path: sourcePath,
|
|
8706
9111
|
ajvErrors: [
|
|
8707
9112
|
{
|
|
8708
9113
|
instancePath: "",
|
|
8709
|
-
message: diagnostic ===
|
|
9114
|
+
message: typeof diagnostic === "string" ? `${loaded.error.code}: ${diagnostic}` : loaded.error.code
|
|
8710
9115
|
}
|
|
8711
9116
|
]
|
|
8712
9117
|
})
|
|
@@ -8719,41 +9124,81 @@ async function scanValidated(roots, opts = {}, capture) {
|
|
|
8719
9124
|
return packErr(
|
|
8720
9125
|
makePackError("pack-malformed-meta", {
|
|
8721
9126
|
path: sourcePath,
|
|
8722
|
-
ajvErrors: [{ instancePath: "", message: "
|
|
9127
|
+
ajvErrors: [{ instancePath: "", message: "Pack source closure read failed" }]
|
|
8723
9128
|
})
|
|
8724
9129
|
);
|
|
8725
9130
|
}
|
|
9131
|
+
const packageCollision = registerPackage(
|
|
9132
|
+
PackageId.format(loaded.value.packageId),
|
|
9133
|
+
sourcePath,
|
|
9134
|
+
"scriptable"
|
|
9135
|
+
);
|
|
9136
|
+
if (packageCollision !== void 0) return packErr(packageCollision);
|
|
8726
9137
|
const meta = projectScriptablePackMeta(loaded.value, sourcePath);
|
|
8727
|
-
|
|
8728
|
-
|
|
8729
|
-
return packErr(
|
|
8730
|
-
makePackError("pack-malformed-meta", {
|
|
8731
|
-
path: sourcePath,
|
|
8732
|
-
ajvErrors: [{ instancePath: "/subAssets", message: topology.error.code }]
|
|
8733
|
-
})
|
|
8734
|
-
);
|
|
8735
|
-
}
|
|
8736
|
-
const declaration = {
|
|
9138
|
+
capture?.declarations.set(sourcePath, {
|
|
9139
|
+
format: "pack.ts",
|
|
8737
9140
|
sourcePath,
|
|
8738
9141
|
sourceRevision: `sha256:${createHash("sha256").update(source).digest("hex")}`,
|
|
8739
|
-
meta,
|
|
9142
|
+
value: meta,
|
|
8740
9143
|
definition: loaded.value,
|
|
8741
9144
|
sourceClosure
|
|
8742
|
-
};
|
|
8743
|
-
capture?.declarations.set(sourcePath, {
|
|
8744
|
-
format: "pack.ts",
|
|
8745
|
-
...declaration,
|
|
8746
|
-
value: meta
|
|
8747
9145
|
});
|
|
8748
|
-
|
|
8749
|
-
|
|
8750
|
-
|
|
8751
|
-
|
|
9146
|
+
}
|
|
9147
|
+
const parentByPackageId = new Map(
|
|
9148
|
+
instanceParents.map((instance) => [instance.packageId.toLowerCase(), instance])
|
|
9149
|
+
);
|
|
9150
|
+
for (const instance of instanceParents) {
|
|
9151
|
+
const parentId = instance.parent.toLowerCase();
|
|
9152
|
+
const parentPath = packageIdToPath.get(parentId);
|
|
9153
|
+
if (parentPath === void 0) {
|
|
9154
|
+
return packErr(
|
|
9155
|
+
makePackError("pack-malformed-pack", {
|
|
9156
|
+
path: instance.path,
|
|
9157
|
+
reason: "pack-parent-not-found",
|
|
9158
|
+
ajvErrors: [
|
|
9159
|
+
{
|
|
9160
|
+
instancePath: "/parent",
|
|
9161
|
+
message: `parent packageId ${instance.parent} was not found`
|
|
9162
|
+
}
|
|
9163
|
+
]
|
|
9164
|
+
})
|
|
9165
|
+
);
|
|
9166
|
+
}
|
|
9167
|
+
const kind = packageKind.get(parentId);
|
|
9168
|
+
if (kind !== "scriptable" && kind !== "instance") {
|
|
9169
|
+
return packErr(
|
|
9170
|
+
makePackError("pack-malformed-pack", {
|
|
9171
|
+
path: instance.path,
|
|
9172
|
+
reason: "pack-parent-has-no-parameters",
|
|
9173
|
+
ajvErrors: [
|
|
9174
|
+
{
|
|
9175
|
+
instancePath: "/parent",
|
|
9176
|
+
message: `parent ${instance.parent} is not a ScriptablePack source with parameters`
|
|
9177
|
+
}
|
|
9178
|
+
]
|
|
9179
|
+
})
|
|
9180
|
+
);
|
|
9181
|
+
}
|
|
9182
|
+
}
|
|
9183
|
+
for (const instance of instanceParents) {
|
|
9184
|
+
const chain = /* @__PURE__ */ new Set();
|
|
9185
|
+
let current = instance.packageId.toLowerCase();
|
|
9186
|
+
while (true) {
|
|
9187
|
+
if (chain.has(current)) {
|
|
8752
9188
|
return packErr(
|
|
8753
|
-
makePackError("pack-
|
|
9189
|
+
makePackError("pack-malformed-pack", {
|
|
9190
|
+
path: instance.path,
|
|
9191
|
+
reason: "pack-parent-cycle",
|
|
9192
|
+
ajvErrors: [
|
|
9193
|
+
{ instancePath: "/parent", message: `parent chain repeats packageId ${current}` }
|
|
9194
|
+
]
|
|
9195
|
+
})
|
|
8754
9196
|
);
|
|
8755
9197
|
}
|
|
8756
|
-
|
|
9198
|
+
chain.add(current);
|
|
9199
|
+
const next = parentByPackageId.get(current);
|
|
9200
|
+
if (next === void 0) break;
|
|
9201
|
+
current = next.parent.toLowerCase();
|
|
8757
9202
|
}
|
|
8758
9203
|
}
|
|
8759
9204
|
const visited = /* @__PURE__ */ new Set();
|
|
@@ -8800,6 +9245,38 @@ async function scanInventory(roots, opts = {}) {
|
|
|
8800
9245
|
for (const sourcePath of scanned.value) {
|
|
8801
9246
|
const declaration = declarations.get(sourcePath);
|
|
8802
9247
|
if (declaration?.format !== "pack.json") continue;
|
|
9248
|
+
if (declaration.value.schemaVersion === "3.0.0") {
|
|
9249
|
+
const parsed = parsePackSourceJson(declaration.value);
|
|
9250
|
+
if (!parsed.ok) {
|
|
9251
|
+
return packErr(
|
|
9252
|
+
makePackError("pack-malformed-pack", {
|
|
9253
|
+
path: sourcePath,
|
|
9254
|
+
ajvErrors: [{ instancePath: "", message: parsed.error.code }]
|
|
9255
|
+
})
|
|
9256
|
+
);
|
|
9257
|
+
}
|
|
9258
|
+
if (parsed.value.format !== "direct") continue;
|
|
9259
|
+
const projected = projectDirectPackJson(parsed.value);
|
|
9260
|
+
if (!projected.ok) {
|
|
9261
|
+
return packErr(
|
|
9262
|
+
makePackError("pack-malformed-pack", {
|
|
9263
|
+
path: sourcePath,
|
|
9264
|
+
ajvErrors: [{ instancePath: "/assets", message: projected.error.code }]
|
|
9265
|
+
})
|
|
9266
|
+
);
|
|
9267
|
+
}
|
|
9268
|
+
for (const [index, asset] of projected.value.assets.entries()) {
|
|
9269
|
+
inventory.push({
|
|
9270
|
+
guid: asset.guid,
|
|
9271
|
+
kind: asset.kind,
|
|
9272
|
+
sourcePath,
|
|
9273
|
+
sourceRevision: declaration.sourceRevision,
|
|
9274
|
+
sourceKey: asset.sourceKey,
|
|
9275
|
+
sourceIndex: index
|
|
9276
|
+
});
|
|
9277
|
+
}
|
|
9278
|
+
continue;
|
|
9279
|
+
}
|
|
8803
9280
|
for (const [index, asset] of declaration.value.assets.entries()) {
|
|
8804
9281
|
inventory.push({
|
|
8805
9282
|
guid: asset.guid,
|