@forgeax/engine-import 0.1.23 → 0.1.25

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.
Files changed (30) hide show
  1. package/README.md +5 -5
  2. package/dist/__tests__/scriptable-pack-build.unit.test.d.ts +2 -0
  3. package/dist/__tests__/scriptable-pack-build.unit.test.d.ts.map +1 -0
  4. package/dist/build-production.d.ts.map +1 -1
  5. package/dist/index.d.ts +4 -4
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.mjs +284 -60
  8. package/dist/index.mjs.map +1 -1
  9. package/dist/{parameterized-scriptable-pack.d.ts → scriptable-pack-build.d.ts} +20 -15
  10. package/dist/scriptable-pack-build.d.ts.map +1 -0
  11. package/dist/scriptable-pack-host.d.ts +15 -13
  12. package/dist/scriptable-pack-host.d.ts.map +1 -1
  13. package/dist/scriptable-pack.d.ts +2 -1
  14. package/dist/scriptable-pack.d.ts.map +1 -1
  15. package/dist/source-package-publication.d.ts +7 -0
  16. package/dist/source-package-publication.d.ts.map +1 -1
  17. package/package.json +8 -8
  18. package/src/__tests__/{parameterized-scriptable-pack.unit.test.ts → scriptable-pack-build.unit.test.ts} +11 -14
  19. package/src/__tests__/scriptable-pack-host.unit.test.ts +53 -5
  20. package/src/__tests__/scriptable-pack-output-producers.unit.test.ts +4 -5
  21. package/src/__tests__/source-package-publication.integration.test.ts +141 -0
  22. package/src/build-production.ts +45 -50
  23. package/src/index.ts +17 -16
  24. package/src/{parameterized-scriptable-pack.ts → scriptable-pack-build.ts} +91 -27
  25. package/src/scriptable-pack-host.ts +48 -40
  26. package/src/scriptable-pack.ts +2 -1
  27. package/src/source-package-publication.ts +242 -10
  28. package/dist/__tests__/parameterized-scriptable-pack.unit.test.d.ts +0 -2
  29. package/dist/__tests__/parameterized-scriptable-pack.unit.test.d.ts.map +0 -1
  30. package/dist/parameterized-scriptable-pack.d.ts.map +0 -1
package/dist/index.mjs CHANGED
@@ -3,20 +3,21 @@ export { IMPORT_ERROR_HINTS, ImportError } from '@forgeax/engine-types';
3
3
  import { resolve, dirname, isAbsolute, relative } from 'path';
4
4
  import { resolveAssetSource, finalizePackageTransportSource, packageTransportRevision, catalogSourcePathFor, buildCatalogProjection, projectPackageCatalog, createRuntimePackPublication, metaPathForGuid } from '@forgeax/engine-pack/build';
5
5
  import { AssetGuid as AssetGuid$1, PackageId as PackageId$1 } from '@forgeax/engine-pack/guid';
6
- import { resolvePackParameterValues, PackageId, isValidPackSourceKey, AssetGuid, parseParameterizedPackJson, projectDirectPackJson, isScriptablePackAssetKind, projectScriptablePackSceneComponents, resolvePackParameterInheritance } from '@forgeax/engine-pack/source';
7
- import { loadParameterizedScriptablePack } from '@forgeax/engine-pack/source-node';
6
+ import { resolvePackParameterValues, PackageId, isValidPackSourceKey, AssetGuid, parsePackSourceJson, projectDirectPackJson, isScriptablePackAssetKind, projectScriptablePackSceneComponents, resolvePackParameterInheritance } from '@forgeax/engine-pack/source';
7
+ import { loadScriptablePack } from '@forgeax/engine-pack/source-node';
8
8
  import { stat, readFile, mkdir, writeFile, rename, rm, readdir } from 'fs/promises';
9
- import { createAcceptedPublication, ddcOutputDigest, DdcGenerationSession, DdcLifecycle } from '@forgeax/engine-ddc';
9
+ import { createAcceptedPublication, ddcOutputDigest, DdcLifecycle, DdcGenerationSession } from '@forgeax/engine-ddc';
10
10
  import { deriveVertexLayoutProjection, normalizeMeshPayload } from '@forgeax/engine-geometry';
11
11
  import { BUILTIN_MESH_ASSETS } from '@forgeax/engine-pack/builtin';
12
12
  import { NativeCookerRegistry } from '@forgeax/engine-pack/native-cooker';
13
- import { isEngineMaterial } from '@forgeax/engine-shader';
13
+ import { isEngineMaterial, DEFAULT_STANDARD_SURFACE_MODULE } from '@forgeax/engine-shader';
14
14
  import { externalizeSceneAsset } from '@forgeax/engine-scene';
15
15
  import { sha256 } from '@noble/hashes/sha2.js';
16
16
  import { bytesToHex } from '@noble/hashes/utils.js';
17
17
  import { MESH_BIN_HEADER_V4_BYTES, writeMeshBinHeader } from '@forgeax/engine-pack/mesh-bin-contract';
18
- import { randomUUID, createHash } from 'crypto';
18
+ import { createHash, randomUUID } from 'crypto';
19
19
  import { validatePack, isScriptablePackAssetKind as isScriptablePackAssetKind$1 } from '@forgeax/engine-pack';
20
+ import { canonicalDdcJson } from '@forgeax/engine-ddc/key';
20
21
 
21
22
  // src/index.ts
22
23
  function invalidProduct(field) {
@@ -784,6 +785,14 @@ function record(value) {
784
785
  function isAsset(value) {
785
786
  return record(value) && typeof value.kind === "string" && isScriptablePackAssetKind(value.kind);
786
787
  }
788
+ function needsMaterialCook(asset) {
789
+ if (asset.kind !== "material" || !Array.isArray(asset.passes)) return false;
790
+ return asset.passes.some((pass) => {
791
+ const module = pass.program.module;
792
+ const surface = pass.program.moduleSlots?.surface;
793
+ return surface !== void 0 && surface !== DEFAULT_STANDARD_SURFACE_MODULE && (module === "forgeax_material::standard" || module === "forgeax::default-standard-pbr" || module === "forgeax_material::pbr-skin" || module === "forgeax::pbr-skin" || module === "forgeax::default-standard-pbr-skin");
794
+ });
795
+ }
787
796
  function clone(value) {
788
797
  return structuredClone(value);
789
798
  }
@@ -923,7 +932,7 @@ function errorCode(value) {
923
932
  function normalizedGuidSet(value) {
924
933
  return value === void 0 ? void 0 : new Set([...value].map((guid) => guid.toLowerCase()));
925
934
  }
926
- async function buildParameterizedScriptablePack(options) {
935
+ async function buildScriptablePack(options) {
927
936
  const subjectPackageId = options.subjectPackageId ?? options.definition.packageId;
928
937
  const availableGuids = normalizedGuidSet(options.availableGuids);
929
938
  const observed = observedReader(options.assetSource);
@@ -947,8 +956,8 @@ async function buildParameterizedScriptablePack(options) {
947
956
  );
948
957
  } else if (options.subjectPackageId !== void 0 && PackageId.format(options.subjectPackageId).toLowerCase() !== PackageId.format(options.definition.packageId).toLowerCase()) {
949
958
  return err({
950
- code: "pack-parent-not-parameterized",
951
- expected: "a parameterized Pack source for an independent instance packageId",
959
+ code: "pack-parent-has-no-parameters",
960
+ expected: "a ScriptablePack source with parameters for an independent instance packageId",
952
961
  hint: "use clone for a zero-parameter Pack instead of building it as an instance",
953
962
  detail: {
954
963
  sourcePath: options.sourcePath,
@@ -1008,6 +1017,9 @@ async function buildParameterizedScriptablePack(options) {
1008
1017
  const imported = [];
1009
1018
  const stagedOutputs = [];
1010
1019
  const localGuids = /* @__PURE__ */ new Set();
1020
+ const materialCookerRegistry = new NativeCookerRegistry();
1021
+ for (const cooker of options.cookers ?? []) materialCookerRegistry.register(cooker);
1022
+ const nativeFingerprints = /* @__PURE__ */ new Map();
1011
1023
  for (const sourceKey of Object.keys(built.value).sort()) {
1012
1024
  if (!isValidPackSourceKey(sourceKey))
1013
1025
  return err(sourceKeyFailure(options.sourcePath, sourceKey));
@@ -1083,12 +1095,40 @@ async function buildParameterizedScriptablePack(options) {
1083
1095
  const invalidProduct2 = productError(options.sourcePath, sourceKey, producer, produced.value);
1084
1096
  if (invalidProduct2 !== void 0) return err(invalidProduct2);
1085
1097
  const product2 = produced.value;
1098
+ let payload = product2.payload;
1099
+ let artifacts2 = product2.artifacts;
1100
+ if (needsMaterialCook(asset) && materialCookerRegistry.get("material") !== void 0) {
1101
+ const cooked = await materialCookerRegistry.runDraft("material", {
1102
+ guid,
1103
+ source: asset,
1104
+ sourceKey,
1105
+ sourcePath: options.sourcePath,
1106
+ refs: product2.refs.map((reference) => reference.guid)
1107
+ });
1108
+ if (!cooked.ok) return err(cooked.error);
1109
+ if (cooked.value.guid.toLowerCase() !== normalizedGuid) {
1110
+ return err({
1111
+ code: "pack-source-output-invalid",
1112
+ expected: "the authored material cooker to preserve the derived AssetGuid",
1113
+ hint: "repair the native material cooker output GUID and rebuild the Pack",
1114
+ detail: {
1115
+ sourcePath: options.sourcePath,
1116
+ sourceKey,
1117
+ expectedGuid: guid,
1118
+ actualGuid: cooked.value.guid
1119
+ }
1120
+ });
1121
+ }
1122
+ payload = cooked.value.payload;
1123
+ artifacts2 = cooked.value.artifacts;
1124
+ nativeFingerprints.set(sourceKey, cooked.value.inputFingerprint);
1125
+ }
1086
1126
  imported.push({
1087
1127
  guid,
1088
1128
  kind: asset.kind,
1089
- payload: product2.payload,
1129
+ payload,
1090
1130
  refs: product2.refs,
1091
- artifacts: product2.artifacts
1131
+ artifacts: artifacts2
1092
1132
  });
1093
1133
  stagedOutputs.push({
1094
1134
  guid: AssetGuid.derive(subjectPackageId, sourceKey),
@@ -1119,7 +1159,7 @@ async function buildParameterizedScriptablePack(options) {
1119
1159
  digest: read.digest
1120
1160
  })
1121
1161
  );
1122
- const inputFingerprint = await digest({
1162
+ const authoredInputFingerprint = await digest({
1123
1163
  packageId: PackageId.format(subjectPackageId),
1124
1164
  sourcePath: options.sourcePath,
1125
1165
  sourceClosure: options.sourceClosure ?? [],
@@ -1129,9 +1169,15 @@ async function buildParameterizedScriptablePack(options) {
1129
1169
  usage,
1130
1170
  digest: evidenceDigest
1131
1171
  })),
1132
- authoringContractVersion: options.authoringContractVersion ?? "parameterized-pack/1",
1172
+ authoringContractVersion: options.authoringContractVersion ?? "scriptable-pack/1",
1133
1173
  producerVersions: options.outputs.versions()
1134
1174
  });
1175
+ const inputFingerprint = nativeFingerprints.size === 0 ? authoredInputFingerprint : await digest({
1176
+ sourceRevision: authoredInputFingerprint,
1177
+ nativeCookers: [...nativeFingerprints.entries()].sort(
1178
+ ([left], [right]) => left.localeCompare(right)
1179
+ )
1180
+ });
1135
1181
  const refs = imported.flatMap((asset) => asset.refs);
1136
1182
  const artifacts = Object.fromEntries(
1137
1183
  imported.flatMap(
@@ -1186,7 +1232,7 @@ function stagedSource(staged, fallback) {
1186
1232
  }
1187
1233
  };
1188
1234
  }
1189
- async function buildParameterizedScriptablePackWorklist(options) {
1235
+ async function buildScriptablePackWorklist(options) {
1190
1236
  const orderedSubjects = [...options.subjects].sort(
1191
1237
  (left, right) => left.sourcePath.localeCompare(right.sourcePath)
1192
1238
  );
@@ -1205,7 +1251,7 @@ async function buildParameterizedScriptablePackWorklist(options) {
1205
1251
  let progress = false;
1206
1252
  const waiting = /* @__PURE__ */ new Set();
1207
1253
  for (const [key, subject] of pending) {
1208
- const result = await buildParameterizedScriptablePack({
1254
+ const result = await buildScriptablePack({
1209
1255
  definition: subject.definition,
1210
1256
  sourcePath: subject.sourcePath,
1211
1257
  ...subject.subjectPackageId === void 0 ? {} : { subjectPackageId: subject.subjectPackageId },
@@ -1213,6 +1259,7 @@ async function buildParameterizedScriptablePackWorklist(options) {
1213
1259
  ...subject.inheritedValues === void 0 ? {} : { inheritedValues: subject.inheritedValues },
1214
1260
  ...subject.sourceClosure === void 0 ? {} : { sourceClosure: subject.sourceClosure },
1215
1261
  outputs: options.outputs,
1262
+ ...options.cookers === void 0 ? {} : { cookers: options.cookers },
1216
1263
  assetSource: stagedSource(staged, options.assetSource),
1217
1264
  availableGuids: /* @__PURE__ */ new Set([...availableGuids, ...staged.keys()]),
1218
1265
  deferReferenceValidation: true
@@ -2113,7 +2160,7 @@ async function declaredPackExternalOutputs(declarations, cookers = [], requiredG
2113
2160
  }
2114
2161
  if (declaration.format !== "pack.json") continue;
2115
2162
  if (declaration.value.schemaVersion === "3.0.0") {
2116
- const parsed = parseParameterizedPackJson(declaration.value);
2163
+ const parsed = parsePackSourceJson(declaration.value);
2117
2164
  if (!parsed.ok || parsed.value.format !== "direct") continue;
2118
2165
  const projected = projectDirectPackJson(parsed.value);
2119
2166
  if (!projected.ok) continue;
@@ -2190,6 +2237,8 @@ async function readCookedAuthoredPack(authoredPack, cookers = [], sourcePath) {
2190
2237
  continue;
2191
2238
  }
2192
2239
  if (isEngineOwnedMaterial(asset)) {
2240
+ hasCookedAsset = true;
2241
+ refsByGuid.set(asset.guid.toLowerCase(), [...asset.refs]);
2193
2242
  assets.push({
2194
2243
  guid: asset.guid,
2195
2244
  kind: asset.kind,
@@ -2432,7 +2481,7 @@ async function prepareDirectPackTransport(input) {
2432
2481
  projectImportProductForBuild(raw.product),
2433
2482
  input.policy
2434
2483
  );
2435
- const facts2 = projectParameterizedPackPublication(raw);
2484
+ const facts2 = projectScriptablePackPublication(raw);
2436
2485
  if (!facts2.ok) return facts2;
2437
2486
  const displaySourcePath2 = input.displaySourcePath ?? input.sourcePath;
2438
2487
  const revision2 = await scriptablePackResourceRevision(displaySourcePath2, raw.inputFingerprint, [
@@ -2463,7 +2512,7 @@ async function prepareDirectPackTransport(input) {
2463
2512
  };
2464
2513
  const outputs = createStandardAssetOutputProducerRegistry();
2465
2514
  outputs.register(createPreExternalizedSceneAssetOutputProducer());
2466
- const built = await buildParameterizedScriptablePack({
2515
+ const built = await buildScriptablePack({
2467
2516
  definition,
2468
2517
  sourcePath: input.sourcePath,
2469
2518
  outputs,
@@ -2526,7 +2575,7 @@ async function prepareDirectPackTransport(input) {
2526
2575
  projectImportProductForBuild(product.product),
2527
2576
  input.policy
2528
2577
  );
2529
- const facts = projectParameterizedPackPublication(product);
2578
+ const facts = projectScriptablePackPublication(product);
2530
2579
  if (!facts.ok) return facts;
2531
2580
  const displaySourcePath = input.displaySourcePath ?? input.sourcePath;
2532
2581
  const revision = await scriptablePackResourceRevision(
@@ -2556,7 +2605,7 @@ async function prepareLegacyPackTransport(authoredPack, cookers, policyFor, sour
2556
2605
  finalized: await finalizePackageTransportSource(cooked.logicalPackage, policyFor(firstGuid))
2557
2606
  };
2558
2607
  }
2559
- async function materializePreparedParameterizedScriptablePack(prepared, paths, sink) {
2608
+ async function materializePreparedScriptablePack(prepared, paths, sink) {
2560
2609
  const { product, finalized } = prepared;
2561
2610
  await sink.writePackage(paths.packagePath, JSON.stringify(finalized.pack));
2562
2611
  for (const artifact of finalized.artifacts) {
@@ -2583,7 +2632,7 @@ async function materializePreparedParameterizedScriptablePack(prepared, paths, s
2583
2632
  }
2584
2633
  return receipts;
2585
2634
  }
2586
- function projectParameterizedPackPublication(product) {
2635
+ function projectScriptablePackPublication(product) {
2587
2636
  const assets = new Map(product.product.assets.map((asset) => [asset.guid.toLowerCase(), asset]));
2588
2637
  const outputs = [];
2589
2638
  for (const staged of product.stagedOutputs) {
@@ -2592,7 +2641,7 @@ function projectParameterizedPackPublication(product) {
2592
2641
  if (asset === void 0 || staged.digest === void 0 || staged.sourceKey === void 0) {
2593
2642
  return err({
2594
2643
  code: "pack-source-output-invalid",
2595
- expected: `parameterized Pack publication output ${guid} to include a product, sourceKey, and digest`,
2644
+ expected: `ScriptablePack publication output ${guid} to include a product, sourceKey, and digest`,
2596
2645
  hint: "repair the dynamic Pack output and rebuild the current generation",
2597
2646
  detail: { stage: "publication", guid }
2598
2647
  });
@@ -2641,7 +2690,7 @@ function snapshotSourceForStagedOutputs(outputs) {
2641
2690
  }
2642
2691
  };
2643
2692
  }
2644
- function composeParameterizedAssetSource(staged, published) {
2693
+ function composeScriptablePackAssetSource(staged, published) {
2645
2694
  if (staged === void 0) return published;
2646
2695
  if (published === void 0) return staged;
2647
2696
  return {
@@ -2652,10 +2701,10 @@ function composeParameterizedAssetSource(staged, published) {
2652
2701
  }
2653
2702
  };
2654
2703
  }
2655
- async function produceParameterizedScriptablePackProducts(options) {
2704
+ async function produceScriptablePackProducts(options) {
2656
2705
  if (options.sources.length === 0) return ok(/* @__PURE__ */ new Map());
2657
2706
  const external = options.declaredExternalOutputs ?? [];
2658
- const assetSource = composeParameterizedAssetSource(
2707
+ const assetSource = composeScriptablePackAssetSource(
2659
2708
  snapshotSourceForStagedOutputs(external),
2660
2709
  options.assetSource
2661
2710
  );
@@ -2671,13 +2720,14 @@ async function produceParameterizedScriptablePackProducts(options) {
2671
2720
  ...source.inheritedValues === void 0 ? {} : { inheritedValues: source.inheritedValues },
2672
2721
  sourceClosure: source.sourceClosure
2673
2722
  }));
2674
- const worklist = await buildParameterizedScriptablePackWorklist({
2723
+ const worklist = await buildScriptablePackWorklist({
2675
2724
  subjects: workItems,
2676
2725
  outputs: createStandardAssetOutputProducerRegistry(
2677
2726
  options.sources.flatMap(
2678
2727
  (source) => projectScriptablePackSceneComponents(source.definition.sceneComponents)
2679
2728
  )
2680
2729
  ),
2730
+ ...options.cookers === void 0 ? {} : { cookers: options.cookers },
2681
2731
  ...assetSource === void 0 ? {} : { assetSource },
2682
2732
  availableGuids,
2683
2733
  ...options.incomingRefs === void 0 ? {} : { incomingRefs: options.incomingRefs },
@@ -2703,7 +2753,7 @@ async function produceParameterizedScriptablePackProducts(options) {
2703
2753
  projectImportProductForBuild(product.product),
2704
2754
  policy
2705
2755
  );
2706
- const facts = projectParameterizedPackPublication(product);
2756
+ const facts = projectScriptablePackPublication(product);
2707
2757
  if (!facts.ok) return facts;
2708
2758
  const revision = await scriptablePackResourceRevision(
2709
2759
  source.displaySourcePath,
@@ -2801,21 +2851,21 @@ function dynamicFailure(context, value) {
2801
2851
  const candidate = value !== null && typeof value === "object" ? value : {};
2802
2852
  const error = candidate;
2803
2853
  throw context.fail({
2804
- code: typeof error.code === "string" ? error.code : "parameterized-pack-build-failed",
2805
- expected: typeof error.expected === "string" ? error.expected : "the parameterized Pack generation to produce a valid terminal result",
2806
- hint: typeof error.hint === "string" ? error.hint : "inspect the parameterized Pack subject and rebuild the current generation",
2854
+ code: typeof error.code === "string" ? error.code : "pack-build-failed",
2855
+ expected: typeof error.expected === "string" ? error.expected : "the Pack source generation to produce a valid terminal result",
2856
+ hint: typeof error.hint === "string" ? error.hint : "inspect the Pack source subject and rebuild the current generation",
2807
2857
  ...error.detail === void 0 ? {} : { detail: error.detail }
2808
2858
  });
2809
2859
  }
2810
- function parameterizedCatalogSourcePath(context, sourcePath) {
2860
+ function packCatalogSourcePath(context, sourcePath) {
2811
2861
  const projected = context.fsForImport.sourceIdentityFor?.(sourcePath);
2812
2862
  const logical = projected === void 0 || isAbsolute(projected) ? relative(context.cwd, sourcePath) : projected;
2813
2863
  return canonicalScriptableSourcePath(logical).replaceAll("\\", "/");
2814
2864
  }
2815
- async function buildParameterizedPackages(context) {
2865
+ async function buildPackSources(context) {
2816
2866
  const subjects = /* @__PURE__ */ new Map();
2817
2867
  for (const [sourcePath, declaration] of context.inventory.sourceDeclarations) {
2818
- if (declaration.format === "pack.ts-parameterized") {
2868
+ if (declaration.format === "pack.ts") {
2819
2869
  const key = PackageId.format(declaration.definition.packageId).toLowerCase();
2820
2870
  subjects.set(key, {
2821
2871
  kind: "source",
@@ -2829,7 +2879,7 @@ async function buildParameterizedPackages(context) {
2829
2879
  if (declaration.format !== "pack.json" || declaration.value.schemaVersion !== "3.0.0") {
2830
2880
  continue;
2831
2881
  }
2832
- const parsed = parseParameterizedPackJson(declaration.value);
2882
+ const parsed = parsePackSourceJson(declaration.value);
2833
2883
  if (!parsed.ok) dynamicFailure(context, parsed.error);
2834
2884
  if (parsed.value.format === "direct") {
2835
2885
  subjects.set(PackageId.format(parsed.value.packageId).toLowerCase(), {
@@ -2881,12 +2931,12 @@ async function buildParameterizedPackages(context) {
2881
2931
  for (const subject of orderedSubjects) {
2882
2932
  if (subject.kind === "source") {
2883
2933
  const packageId = PackageId.format(subject.packageId);
2884
- const loaded = await loadParameterizedScriptablePack(subject.sourcePath);
2934
+ const loaded = await loadScriptablePack(subject.sourcePath);
2885
2935
  if (!loaded.ok) dynamicFailure(context, loaded.error);
2886
2936
  if (PackageId.format(loaded.value.packageId) !== packageId) {
2887
2937
  dynamicFailure(context, {
2888
2938
  code: "pack-source-revision-conflict",
2889
- expected: "the parameterized source packageId to remain fixed during production",
2939
+ expected: "the ScriptablePack source packageId to remain fixed during production",
2890
2940
  hint: "retry after source writes settle and rebuild the current generation",
2891
2941
  detail: {
2892
2942
  sourcePath: subject.sourcePath,
@@ -2897,7 +2947,7 @@ async function buildParameterizedPackages(context) {
2897
2947
  }
2898
2948
  inputs.push({
2899
2949
  sourcePath: subject.sourcePath,
2900
- displaySourcePath: parameterizedCatalogSourcePath(context, subject.sourcePath),
2950
+ displaySourcePath: packCatalogSourcePath(context, subject.sourcePath),
2901
2951
  definition: loaded.value,
2902
2952
  sourceClosure: subject.sourceClosure,
2903
2953
  publicationGeneration: context.generation,
@@ -2924,18 +2974,18 @@ async function buildParameterizedPackages(context) {
2924
2974
  const root = sourceSubject(resolved.value.rootPackageId);
2925
2975
  if (root === void 0) {
2926
2976
  dynamicFailure(context, {
2927
- code: "pack-parent-not-parameterized",
2928
- expected: "the instance parent chain to terminate at a parameterized source",
2929
- hint: "point the instance at a parameterized pack.ts source",
2977
+ code: "pack-parent-has-no-parameters",
2978
+ expected: "the instance parent chain to terminate at a ScriptablePack source",
2979
+ hint: "point the instance at a ScriptablePack *.pack.ts source with parameters",
2930
2980
  detail: { packageId: PackageId.format(subject.packageId) }
2931
2981
  });
2932
2982
  }
2933
- const loaded = await loadParameterizedScriptablePack(root.sourcePath);
2983
+ const loaded = await loadScriptablePack(root.sourcePath);
2934
2984
  if (!loaded.ok) dynamicFailure(context, loaded.error);
2935
2985
  if (PackageId.format(loaded.value.packageId) !== PackageId.format(root.packageId)) {
2936
2986
  dynamicFailure(context, {
2937
2987
  code: "pack-source-revision-conflict",
2938
- expected: "the parameterized parent packageId to remain fixed during production",
2988
+ expected: "the ScriptablePack parent packageId to remain fixed during production",
2939
2989
  hint: "retry after source writes settle and rebuild the current generation",
2940
2990
  detail: {
2941
2991
  sourcePath: root.sourcePath,
@@ -2947,7 +2997,7 @@ async function buildParameterizedPackages(context) {
2947
2997
  const packageId = PackageId.format(subject.packageId);
2948
2998
  inputs.push({
2949
2999
  sourcePath: subject.sourcePath,
2950
- displaySourcePath: parameterizedCatalogSourcePath(context, subject.sourcePath),
3000
+ displaySourcePath: packCatalogSourcePath(context, subject.sourcePath),
2951
3001
  definition: loaded.value,
2952
3002
  sourceClosure: root.sourceClosure,
2953
3003
  subjectPackageId: subject.packageId,
@@ -2976,9 +3026,10 @@ async function buildParameterizedPackages(context) {
2976
3026
  }
2977
3027
  );
2978
3028
  const availableGuids = new Set(requiredGuids.map((guid) => AssetGuid$1.format(guid).toLowerCase()));
2979
- const built = await produceParameterizedScriptablePackProducts({
3029
+ const built = await produceScriptablePackProducts({
2980
3030
  sources: inputs,
2981
3031
  declaredExternalOutputs: externalOutputs,
3032
+ cookers: context.cookers,
2982
3033
  availableGuids
2983
3034
  });
2984
3035
  if (!built.ok) dynamicFailure(context, built.error);
@@ -2987,9 +3038,9 @@ async function buildParameterizedPackages(context) {
2987
3038
  const prepared = built.value.get(input.displaySourcePath);
2988
3039
  if (prepared === void 0) {
2989
3040
  dynamicFailure(context, {
2990
- code: "parameterized-pack-build-failed",
3041
+ code: "pack-build-failed",
2991
3042
  expected: "the worklist to return one prepared result per source subject",
2992
- hint: "rerun the parameterized Pack generation from a clean inventory",
3043
+ hint: "rerun Pack source generation from a clean inventory",
2993
3044
  detail: { sourcePath: input.sourcePath }
2994
3045
  });
2995
3046
  }
@@ -3105,13 +3156,13 @@ async function emitAuthoredPack(work, guidSeen, entry, availableGuids) {
3105
3156
  });
3106
3157
  }
3107
3158
  if (declaration.value.schemaVersion === "3.0.0") {
3108
- const parsed = parseParameterizedPackJson(declaration.value);
3159
+ const parsed = parsePackSourceJson(declaration.value);
3109
3160
  if (!parsed.ok) dynamicFailure(work.context, parsed.error);
3110
3161
  if (parsed.value.format !== "direct") {
3111
3162
  dynamicFailure(work.context, {
3112
3163
  code: "catalog-declaration-missing",
3113
3164
  expected: "a direct v3 Pack declaration for an indexed authored output",
3114
- hint: "instances are built from their parameterized parent and do not have direct Catalog rows",
3165
+ hint: "instances are built from their ScriptablePack parent and do not have direct Catalog rows",
3115
3166
  detail: { stage: "scan", sourcePath: packPath }
3116
3167
  });
3117
3168
  }
@@ -3210,7 +3261,7 @@ async function emitAuthoredPack(work, guidSeen, entry, availableGuids) {
3210
3261
  guidSeen.add(guid.toLowerCase());
3211
3262
  }
3212
3263
  }
3213
- async function emitParameterizedPack(work, guidSeen, bundle) {
3264
+ async function emitScriptablePack(work, guidSeen, bundle) {
3214
3265
  const { input, prepared } = bundle;
3215
3266
  const packageId = PackageId.format(input.subjectPackageId ?? input.definition.packageId);
3216
3267
  const runtimePublication = createRuntimePackPublication({
@@ -3385,7 +3436,7 @@ async function emitBuildEntry(work, guidSeen, entry, availableGuids) {
3385
3436
  });
3386
3437
  }
3387
3438
  async function produceBuildAssets(context) {
3388
- const dynamicBundles = await buildParameterizedPackages(context);
3439
+ const dynamicBundles = await buildPackSources(context);
3389
3440
  const entries = [
3390
3441
  ...context.inventory.entries,
3391
3442
  ...dynamicBundles.flatMap((bundle) => bundle.entries)
@@ -3395,7 +3446,7 @@ async function produceBuildAssets(context) {
3395
3446
  const guidSeen = /* @__PURE__ */ new Set();
3396
3447
  const work = { importedEntries, context };
3397
3448
  for (const bundle of dynamicBundles) {
3398
- await emitParameterizedPack(work, guidSeen, bundle);
3449
+ await emitScriptablePack(work, guidSeen, bundle);
3399
3450
  }
3400
3451
  for (const entry of importedEntries) {
3401
3452
  if (!guidSeen.has(entry.guid.toLowerCase()))
@@ -4318,6 +4369,176 @@ function importPublicationFailure(error) {
4318
4369
  diagnostic: error
4319
4370
  };
4320
4371
  }
4372
+ function publicationArtifacts(transport) {
4373
+ return Object.fromEntries(
4374
+ (transport?.artifacts ?? []).map((artifact) => [
4375
+ artifact.path,
4376
+ { mediaType: artifact.mediaType, bytes: artifact.bytes }
4377
+ ])
4378
+ );
4379
+ }
4380
+ function publicationContext(input) {
4381
+ return {
4382
+ sourceMeta: "<import-publication>",
4383
+ anchorGuid: input.guid,
4384
+ affectedGuids: input.publishedGuids,
4385
+ producer: "source-package/import-publication",
4386
+ importer: "import-publication"
4387
+ };
4388
+ }
4389
+ function validatePublicationArtifactClosure(input) {
4390
+ const context = publicationContext(input);
4391
+ const pack = input.pack;
4392
+ if (pack === null || typeof pack !== "object" || pack.schemaVersion !== "2.0.0" || pack.kind !== "internal-text-package") {
4393
+ return ok(publicationArtifacts(input.transport));
4394
+ }
4395
+ const assets = pack.assets;
4396
+ if (!Array.isArray(assets)) {
4397
+ return err(
4398
+ sourcePackageError("source-package-publication-invalid", context, {
4399
+ stage: "route-integrity",
4400
+ reason: "published Pack does not contain an assets array"
4401
+ })
4402
+ );
4403
+ }
4404
+ const required = /* @__PURE__ */ new Map();
4405
+ for (const asset of assets) {
4406
+ if (asset === null || typeof asset !== "object") {
4407
+ return err(
4408
+ sourcePackageError("source-package-publication-invalid", context, {
4409
+ stage: "route-integrity",
4410
+ reason: "published Pack contains a non-object asset row"
4411
+ })
4412
+ );
4413
+ }
4414
+ const rawArtifacts = asset.artifacts;
4415
+ if (rawArtifacts === void 0) continue;
4416
+ if (rawArtifacts === null || typeof rawArtifacts !== "object" || Array.isArray(rawArtifacts)) {
4417
+ return err(
4418
+ sourcePackageError("source-package-publication-invalid", context, {
4419
+ stage: "route-integrity",
4420
+ reason: "published Pack contains an invalid asset artifact map"
4421
+ })
4422
+ );
4423
+ }
4424
+ for (const [localKey, rawDescriptor] of Object.entries(
4425
+ rawArtifacts
4426
+ )) {
4427
+ if (rawDescriptor === null || typeof rawDescriptor !== "object") {
4428
+ return err(
4429
+ sourcePackageError("source-package-publication-invalid", context, {
4430
+ stage: "route-integrity",
4431
+ reason: `artifact descriptor ${localKey} is not an object`
4432
+ })
4433
+ );
4434
+ }
4435
+ const descriptor = rawDescriptor;
4436
+ const path = descriptor.path;
4437
+ if (typeof path !== "string" || path.length === 0) {
4438
+ return err(
4439
+ sourcePackageError("source-package-publication-invalid", context, {
4440
+ stage: "route-integrity",
4441
+ reason: `artifact descriptor ${localKey} has no package-relative path`
4442
+ })
4443
+ );
4444
+ }
4445
+ const mediaType = descriptor.mediaType;
4446
+ const byteLength = descriptor.byteLength;
4447
+ const integrityValue = descriptor.integrity;
4448
+ const integrity = integrityValue !== null && typeof integrityValue === "object" ? {
4449
+ algorithm: integrityValue.algorithm,
4450
+ digest: integrityValue.digest
4451
+ } : void 0;
4452
+ if (mediaType !== void 0 && typeof mediaType !== "string" || byteLength !== void 0 && (!Number.isSafeInteger(byteLength) || byteLength < 0) || integrityValue !== void 0 && (integrity === void 0 || typeof integrity.algorithm !== "string" || typeof integrity.digest !== "string")) {
4453
+ return err(
4454
+ sourcePackageError("source-package-publication-invalid", context, {
4455
+ stage: "route-integrity",
4456
+ reason: `artifact descriptor ${path} has invalid metadata`
4457
+ })
4458
+ );
4459
+ }
4460
+ if (required.has(path)) {
4461
+ return err(
4462
+ sourcePackageError("source-package-publication-invalid", context, {
4463
+ stage: "route-integrity",
4464
+ reason: `artifact path ${path} is declared more than once`
4465
+ })
4466
+ );
4467
+ }
4468
+ required.set(path, {
4469
+ ...typeof mediaType === "string" ? { mediaType } : {},
4470
+ ...typeof byteLength === "number" ? { byteLength } : {},
4471
+ ...integrity !== void 0 && typeof integrity.algorithm === "string" && typeof integrity.digest === "string" ? { integrity: { algorithm: integrity.algorithm, digest: integrity.digest } } : {}
4472
+ });
4473
+ }
4474
+ }
4475
+ const available = /* @__PURE__ */ new Map();
4476
+ const duplicatePaths = [];
4477
+ for (const artifact of input.transport?.artifacts ?? []) {
4478
+ if (available.has(artifact.path)) duplicatePaths.push(artifact.path);
4479
+ available.set(artifact.path, artifact);
4480
+ }
4481
+ const missing = [];
4482
+ const mismatched = [...duplicatePaths.map((path) => `${path}: duplicate body`)];
4483
+ for (const path of available.keys()) {
4484
+ if (!required.has(path)) mismatched.push(`${path}: unexpected body`);
4485
+ }
4486
+ for (const [path, descriptor] of required) {
4487
+ const artifact = available.get(path);
4488
+ if (artifact === void 0) {
4489
+ missing.push(path);
4490
+ continue;
4491
+ }
4492
+ if (!(artifact.bytes instanceof Uint8Array)) {
4493
+ mismatched.push(`${path}: body is not Uint8Array`);
4494
+ continue;
4495
+ }
4496
+ if (descriptor.mediaType !== void 0 && artifact.mediaType !== descriptor.mediaType) {
4497
+ mismatched.push(`${path}: media type mismatch`);
4498
+ }
4499
+ if (descriptor.byteLength !== void 0 && artifact.bytes.byteLength !== descriptor.byteLength) {
4500
+ mismatched.push(`${path}: byte length mismatch`);
4501
+ }
4502
+ if (descriptor.integrity !== void 0) {
4503
+ const actualDigest = `sha256:${createHash("sha256").update(artifact.bytes).digest("hex")}`;
4504
+ if (descriptor.integrity.algorithm !== "sha256" || descriptor.integrity.digest !== actualDigest) {
4505
+ mismatched.push(`${path}: integrity mismatch`);
4506
+ }
4507
+ }
4508
+ }
4509
+ if (missing.length > 0 || mismatched.length > 0) {
4510
+ return err(
4511
+ sourcePackageError("source-package-publication-invalid", context, {
4512
+ stage: "route-integrity",
4513
+ reason: "Pack artifact closure is incomplete or mismatched",
4514
+ ...missing.length === 0 ? {} : { missing },
4515
+ ...mismatched.length === 0 ? {} : { unexpected: mismatched }
4516
+ })
4517
+ );
4518
+ }
4519
+ if (input.transport !== void 0) {
4520
+ let transportedPack;
4521
+ try {
4522
+ transportedPack = JSON.parse(input.transport.body);
4523
+ } catch {
4524
+ return err(
4525
+ sourcePackageError("source-package-publication-invalid", context, {
4526
+ stage: "route-integrity",
4527
+ reason: "transport body is not valid JSON for the published Pack"
4528
+ })
4529
+ );
4530
+ }
4531
+ if (canonicalDdcJson(transportedPack) !== canonicalDdcJson(pack)) {
4532
+ return err(
4533
+ sourcePackageError("source-package-publication-invalid", context, {
4534
+ stage: "route-integrity",
4535
+ reason: "transport body does not match the published Pack"
4536
+ })
4537
+ );
4538
+ }
4539
+ }
4540
+ return ok(publicationArtifacts(input.transport));
4541
+ }
4321
4542
  function projectImportPublication(input, head, observedAt) {
4322
4543
  const digest3 = head.currentKey ?? input.desiredKey;
4323
4544
  const revision = { digest: digest3, observedAt, rootId: input.root };
@@ -4345,6 +4566,15 @@ async function publishImportPublication(input) {
4345
4566
  return commitImportPublication(staged.candidate);
4346
4567
  }
4347
4568
  async function stageImportPublication(input) {
4569
+ const validatedArtifacts = validatePublicationArtifactClosure(input);
4570
+ if (!validatedArtifacts.ok) {
4571
+ return {
4572
+ ok: false,
4573
+ error: importPublicationFailure(validatedArtifacts.error),
4574
+ head: await inspectHead(input.root, input.guid, input.desiredKey)
4575
+ };
4576
+ }
4577
+ const artifacts = validatedArtifacts.value;
4348
4578
  const staged = await stageSourcePackageDdc({
4349
4579
  root: input.root,
4350
4580
  entry: {
@@ -4352,7 +4582,7 @@ async function stageImportPublication(input) {
4352
4582
  guid: input.guid,
4353
4583
  payload: input.pack,
4354
4584
  refs: [],
4355
- artifacts: {},
4585
+ artifacts,
4356
4586
  receipt: {
4357
4587
  guid: input.guid,
4358
4588
  key: input.desiredKey,
@@ -4362,17 +4592,11 @@ async function stageImportPublication(input) {
4362
4592
  guid: input.guid,
4363
4593
  payload: input.pack,
4364
4594
  refs: [],
4365
- artifacts: {}
4595
+ artifacts
4366
4596
  })
4367
4597
  }
4368
4598
  },
4369
- context: {
4370
- sourceMeta: "<import-publication>",
4371
- anchorGuid: input.guid,
4372
- affectedGuids: input.publishedGuids,
4373
- producer: "source-package/import-publication",
4374
- importer: "import-publication"
4375
- }
4599
+ context: publicationContext(input)
4376
4600
  });
4377
4601
  if (!staged.ok) {
4378
4602
  return {
@@ -4460,6 +4684,6 @@ async function restoreImportPublication(candidate) {
4460
4684
  await candidate.ddc.session.restoreEntry(candidate.ddc);
4461
4685
  }
4462
4686
 
4463
- export { AssetOutputProducerRegistry, DEFAULT_CATALOG_IMPORTER_KEYS, ImporterRegistry, SHADER_RESERVED_IMPORTER_KEY, buildCatalogResult, buildParameterizedScriptablePack, buildParameterizedScriptablePackWorklist, canonicalScriptableSourcePath, catalogImporterPolicy, commitImportPublication, containsSourcePackageError, createImportProduct, createPreExternalizedSceneAssetOutputProducer, createSceneAssetOutputProducer, createScriptablePackFileAssetSnapshotSource, createScriptablePackStagedAssetSnapshotSource, createStandardAssetOutputProducerRegistry, declaredPackExternalOutputs, deriveDefaultLodScreenCoverages, discardImportPublication, finalizeImportProducts, finalizeSourcePackage, iesImporter, materialAssetOutputProducer, materializePreparedParameterizedScriptablePack, meshAssetOutputProducer, normaliseForPack, normalizeSourcePackageError, packMeshBinV4, parseLm63TypeC, parseProducerReadiness, prepareDirectPackTransport, prepareLegacyPackTransport, produceBuildAssets, produceParameterizedScriptablePackProducts, produceSourcePackage, projectImportProductForBuild, publishImportPublication, readCookedAuthoredPack, readFloat16LE, reconcileMeshLodMeta, resampleTypeC, restoreImportPublication, runImport, sourceDeclarationForCatalogPath, sourcePackageAssetsByGuid, sourcePackageError, stageImportPublication, textureAssetOutputProducer, validateIesProfilePayload, validateMeshLodContract };
4687
+ export { AssetOutputProducerRegistry, DEFAULT_CATALOG_IMPORTER_KEYS, ImporterRegistry, SHADER_RESERVED_IMPORTER_KEY, buildCatalogResult, buildScriptablePack, buildScriptablePackWorklist, canonicalScriptableSourcePath, catalogImporterPolicy, commitImportPublication, containsSourcePackageError, createImportProduct, createPreExternalizedSceneAssetOutputProducer, createSceneAssetOutputProducer, createScriptablePackFileAssetSnapshotSource, createScriptablePackStagedAssetSnapshotSource, createStandardAssetOutputProducerRegistry, declaredPackExternalOutputs, deriveDefaultLodScreenCoverages, discardImportPublication, finalizeImportProducts, finalizeSourcePackage, iesImporter, materialAssetOutputProducer, materializePreparedScriptablePack, meshAssetOutputProducer, normaliseForPack, normalizeSourcePackageError, packMeshBinV4, parseLm63TypeC, parseProducerReadiness, prepareDirectPackTransport, prepareLegacyPackTransport, produceBuildAssets, produceScriptablePackProducts, produceSourcePackage, projectImportProductForBuild, publishImportPublication, readCookedAuthoredPack, readFloat16LE, reconcileMeshLodMeta, resampleTypeC, restoreImportPublication, runImport, sourceDeclarationForCatalogPath, sourcePackageAssetsByGuid, sourcePackageError, stageImportPublication, textureAssetOutputProducer, validateIesProfilePayload, validateMeshLodContract };
4464
4688
  //# sourceMappingURL=index.mjs.map
4465
4689
  //# sourceMappingURL=index.mjs.map