@forgeax/engine-import 0.1.23 → 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.
Files changed (29) 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 +230 -56
  8. package/dist/index.mjs.map +1 -1
  9. package/dist/{parameterized-scriptable-pack.d.ts → scriptable-pack-build.d.ts} +15 -15
  10. package/dist/scriptable-pack-build.d.ts.map +1 -0
  11. package/dist/scriptable-pack-host.d.ts +13 -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 +5 -5
  20. package/src/__tests__/source-package-publication.integration.test.ts +141 -0
  21. package/src/build-production.ts +44 -50
  22. package/src/index.ts +17 -16
  23. package/src/{parameterized-scriptable-pack.ts → scriptable-pack-build.ts} +24 -24
  24. package/src/scriptable-pack-host.ts +38 -40
  25. package/src/scriptable-pack.ts +2 -1
  26. package/src/source-package-publication.ts +242 -10
  27. package/dist/__tests__/parameterized-scriptable-pack.unit.test.d.ts +0 -2
  28. package/dist/__tests__/parameterized-scriptable-pack.unit.test.d.ts.map +0 -1
  29. package/dist/parameterized-scriptable-pack.d.ts.map +0 -1
package/dist/index.mjs CHANGED
@@ -3,10 +3,10 @@ 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';
@@ -15,8 +15,9 @@ 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) {
@@ -923,7 +924,7 @@ function errorCode(value) {
923
924
  function normalizedGuidSet(value) {
924
925
  return value === void 0 ? void 0 : new Set([...value].map((guid) => guid.toLowerCase()));
925
926
  }
926
- async function buildParameterizedScriptablePack(options) {
927
+ async function buildScriptablePack(options) {
927
928
  const subjectPackageId = options.subjectPackageId ?? options.definition.packageId;
928
929
  const availableGuids = normalizedGuidSet(options.availableGuids);
929
930
  const observed = observedReader(options.assetSource);
@@ -947,8 +948,8 @@ async function buildParameterizedScriptablePack(options) {
947
948
  );
948
949
  } else if (options.subjectPackageId !== void 0 && PackageId.format(options.subjectPackageId).toLowerCase() !== PackageId.format(options.definition.packageId).toLowerCase()) {
949
950
  return err({
950
- code: "pack-parent-not-parameterized",
951
- expected: "a parameterized Pack source for an independent instance packageId",
951
+ code: "pack-parent-has-no-parameters",
952
+ expected: "a ScriptablePack source with parameters for an independent instance packageId",
952
953
  hint: "use clone for a zero-parameter Pack instead of building it as an instance",
953
954
  detail: {
954
955
  sourcePath: options.sourcePath,
@@ -1129,7 +1130,7 @@ async function buildParameterizedScriptablePack(options) {
1129
1130
  usage,
1130
1131
  digest: evidenceDigest
1131
1132
  })),
1132
- authoringContractVersion: options.authoringContractVersion ?? "parameterized-pack/1",
1133
+ authoringContractVersion: options.authoringContractVersion ?? "scriptable-pack/1",
1133
1134
  producerVersions: options.outputs.versions()
1134
1135
  });
1135
1136
  const refs = imported.flatMap((asset) => asset.refs);
@@ -1186,7 +1187,7 @@ function stagedSource(staged, fallback) {
1186
1187
  }
1187
1188
  };
1188
1189
  }
1189
- async function buildParameterizedScriptablePackWorklist(options) {
1190
+ async function buildScriptablePackWorklist(options) {
1190
1191
  const orderedSubjects = [...options.subjects].sort(
1191
1192
  (left, right) => left.sourcePath.localeCompare(right.sourcePath)
1192
1193
  );
@@ -1205,7 +1206,7 @@ async function buildParameterizedScriptablePackWorklist(options) {
1205
1206
  let progress = false;
1206
1207
  const waiting = /* @__PURE__ */ new Set();
1207
1208
  for (const [key, subject] of pending) {
1208
- const result = await buildParameterizedScriptablePack({
1209
+ const result = await buildScriptablePack({
1209
1210
  definition: subject.definition,
1210
1211
  sourcePath: subject.sourcePath,
1211
1212
  ...subject.subjectPackageId === void 0 ? {} : { subjectPackageId: subject.subjectPackageId },
@@ -2113,7 +2114,7 @@ async function declaredPackExternalOutputs(declarations, cookers = [], requiredG
2113
2114
  }
2114
2115
  if (declaration.format !== "pack.json") continue;
2115
2116
  if (declaration.value.schemaVersion === "3.0.0") {
2116
- const parsed = parseParameterizedPackJson(declaration.value);
2117
+ const parsed = parsePackSourceJson(declaration.value);
2117
2118
  if (!parsed.ok || parsed.value.format !== "direct") continue;
2118
2119
  const projected = projectDirectPackJson(parsed.value);
2119
2120
  if (!projected.ok) continue;
@@ -2432,7 +2433,7 @@ async function prepareDirectPackTransport(input) {
2432
2433
  projectImportProductForBuild(raw.product),
2433
2434
  input.policy
2434
2435
  );
2435
- const facts2 = projectParameterizedPackPublication(raw);
2436
+ const facts2 = projectScriptablePackPublication(raw);
2436
2437
  if (!facts2.ok) return facts2;
2437
2438
  const displaySourcePath2 = input.displaySourcePath ?? input.sourcePath;
2438
2439
  const revision2 = await scriptablePackResourceRevision(displaySourcePath2, raw.inputFingerprint, [
@@ -2463,7 +2464,7 @@ async function prepareDirectPackTransport(input) {
2463
2464
  };
2464
2465
  const outputs = createStandardAssetOutputProducerRegistry();
2465
2466
  outputs.register(createPreExternalizedSceneAssetOutputProducer());
2466
- const built = await buildParameterizedScriptablePack({
2467
+ const built = await buildScriptablePack({
2467
2468
  definition,
2468
2469
  sourcePath: input.sourcePath,
2469
2470
  outputs,
@@ -2526,7 +2527,7 @@ async function prepareDirectPackTransport(input) {
2526
2527
  projectImportProductForBuild(product.product),
2527
2528
  input.policy
2528
2529
  );
2529
- const facts = projectParameterizedPackPublication(product);
2530
+ const facts = projectScriptablePackPublication(product);
2530
2531
  if (!facts.ok) return facts;
2531
2532
  const displaySourcePath = input.displaySourcePath ?? input.sourcePath;
2532
2533
  const revision = await scriptablePackResourceRevision(
@@ -2556,7 +2557,7 @@ async function prepareLegacyPackTransport(authoredPack, cookers, policyFor, sour
2556
2557
  finalized: await finalizePackageTransportSource(cooked.logicalPackage, policyFor(firstGuid))
2557
2558
  };
2558
2559
  }
2559
- async function materializePreparedParameterizedScriptablePack(prepared, paths, sink) {
2560
+ async function materializePreparedScriptablePack(prepared, paths, sink) {
2560
2561
  const { product, finalized } = prepared;
2561
2562
  await sink.writePackage(paths.packagePath, JSON.stringify(finalized.pack));
2562
2563
  for (const artifact of finalized.artifacts) {
@@ -2583,7 +2584,7 @@ async function materializePreparedParameterizedScriptablePack(prepared, paths, s
2583
2584
  }
2584
2585
  return receipts;
2585
2586
  }
2586
- function projectParameterizedPackPublication(product) {
2587
+ function projectScriptablePackPublication(product) {
2587
2588
  const assets = new Map(product.product.assets.map((asset) => [asset.guid.toLowerCase(), asset]));
2588
2589
  const outputs = [];
2589
2590
  for (const staged of product.stagedOutputs) {
@@ -2592,7 +2593,7 @@ function projectParameterizedPackPublication(product) {
2592
2593
  if (asset === void 0 || staged.digest === void 0 || staged.sourceKey === void 0) {
2593
2594
  return err({
2594
2595
  code: "pack-source-output-invalid",
2595
- expected: `parameterized Pack publication output ${guid} to include a product, sourceKey, and digest`,
2596
+ expected: `ScriptablePack publication output ${guid} to include a product, sourceKey, and digest`,
2596
2597
  hint: "repair the dynamic Pack output and rebuild the current generation",
2597
2598
  detail: { stage: "publication", guid }
2598
2599
  });
@@ -2641,7 +2642,7 @@ function snapshotSourceForStagedOutputs(outputs) {
2641
2642
  }
2642
2643
  };
2643
2644
  }
2644
- function composeParameterizedAssetSource(staged, published) {
2645
+ function composeScriptablePackAssetSource(staged, published) {
2645
2646
  if (staged === void 0) return published;
2646
2647
  if (published === void 0) return staged;
2647
2648
  return {
@@ -2652,10 +2653,10 @@ function composeParameterizedAssetSource(staged, published) {
2652
2653
  }
2653
2654
  };
2654
2655
  }
2655
- async function produceParameterizedScriptablePackProducts(options) {
2656
+ async function produceScriptablePackProducts(options) {
2656
2657
  if (options.sources.length === 0) return ok(/* @__PURE__ */ new Map());
2657
2658
  const external = options.declaredExternalOutputs ?? [];
2658
- const assetSource = composeParameterizedAssetSource(
2659
+ const assetSource = composeScriptablePackAssetSource(
2659
2660
  snapshotSourceForStagedOutputs(external),
2660
2661
  options.assetSource
2661
2662
  );
@@ -2671,7 +2672,7 @@ async function produceParameterizedScriptablePackProducts(options) {
2671
2672
  ...source.inheritedValues === void 0 ? {} : { inheritedValues: source.inheritedValues },
2672
2673
  sourceClosure: source.sourceClosure
2673
2674
  }));
2674
- const worklist = await buildParameterizedScriptablePackWorklist({
2675
+ const worklist = await buildScriptablePackWorklist({
2675
2676
  subjects: workItems,
2676
2677
  outputs: createStandardAssetOutputProducerRegistry(
2677
2678
  options.sources.flatMap(
@@ -2703,7 +2704,7 @@ async function produceParameterizedScriptablePackProducts(options) {
2703
2704
  projectImportProductForBuild(product.product),
2704
2705
  policy
2705
2706
  );
2706
- const facts = projectParameterizedPackPublication(product);
2707
+ const facts = projectScriptablePackPublication(product);
2707
2708
  if (!facts.ok) return facts;
2708
2709
  const revision = await scriptablePackResourceRevision(
2709
2710
  source.displaySourcePath,
@@ -2801,21 +2802,21 @@ function dynamicFailure(context, value) {
2801
2802
  const candidate = value !== null && typeof value === "object" ? value : {};
2802
2803
  const error = candidate;
2803
2804
  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",
2805
+ code: typeof error.code === "string" ? error.code : "pack-build-failed",
2806
+ expected: typeof error.expected === "string" ? error.expected : "the Pack source generation to produce a valid terminal result",
2807
+ hint: typeof error.hint === "string" ? error.hint : "inspect the Pack source subject and rebuild the current generation",
2807
2808
  ...error.detail === void 0 ? {} : { detail: error.detail }
2808
2809
  });
2809
2810
  }
2810
- function parameterizedCatalogSourcePath(context, sourcePath) {
2811
+ function packCatalogSourcePath(context, sourcePath) {
2811
2812
  const projected = context.fsForImport.sourceIdentityFor?.(sourcePath);
2812
2813
  const logical = projected === void 0 || isAbsolute(projected) ? relative(context.cwd, sourcePath) : projected;
2813
2814
  return canonicalScriptableSourcePath(logical).replaceAll("\\", "/");
2814
2815
  }
2815
- async function buildParameterizedPackages(context) {
2816
+ async function buildPackSources(context) {
2816
2817
  const subjects = /* @__PURE__ */ new Map();
2817
2818
  for (const [sourcePath, declaration] of context.inventory.sourceDeclarations) {
2818
- if (declaration.format === "pack.ts-parameterized") {
2819
+ if (declaration.format === "pack.ts") {
2819
2820
  const key = PackageId.format(declaration.definition.packageId).toLowerCase();
2820
2821
  subjects.set(key, {
2821
2822
  kind: "source",
@@ -2829,7 +2830,7 @@ async function buildParameterizedPackages(context) {
2829
2830
  if (declaration.format !== "pack.json" || declaration.value.schemaVersion !== "3.0.0") {
2830
2831
  continue;
2831
2832
  }
2832
- const parsed = parseParameterizedPackJson(declaration.value);
2833
+ const parsed = parsePackSourceJson(declaration.value);
2833
2834
  if (!parsed.ok) dynamicFailure(context, parsed.error);
2834
2835
  if (parsed.value.format === "direct") {
2835
2836
  subjects.set(PackageId.format(parsed.value.packageId).toLowerCase(), {
@@ -2881,12 +2882,12 @@ async function buildParameterizedPackages(context) {
2881
2882
  for (const subject of orderedSubjects) {
2882
2883
  if (subject.kind === "source") {
2883
2884
  const packageId = PackageId.format(subject.packageId);
2884
- const loaded = await loadParameterizedScriptablePack(subject.sourcePath);
2885
+ const loaded = await loadScriptablePack(subject.sourcePath);
2885
2886
  if (!loaded.ok) dynamicFailure(context, loaded.error);
2886
2887
  if (PackageId.format(loaded.value.packageId) !== packageId) {
2887
2888
  dynamicFailure(context, {
2888
2889
  code: "pack-source-revision-conflict",
2889
- expected: "the parameterized source packageId to remain fixed during production",
2890
+ expected: "the ScriptablePack source packageId to remain fixed during production",
2890
2891
  hint: "retry after source writes settle and rebuild the current generation",
2891
2892
  detail: {
2892
2893
  sourcePath: subject.sourcePath,
@@ -2897,7 +2898,7 @@ async function buildParameterizedPackages(context) {
2897
2898
  }
2898
2899
  inputs.push({
2899
2900
  sourcePath: subject.sourcePath,
2900
- displaySourcePath: parameterizedCatalogSourcePath(context, subject.sourcePath),
2901
+ displaySourcePath: packCatalogSourcePath(context, subject.sourcePath),
2901
2902
  definition: loaded.value,
2902
2903
  sourceClosure: subject.sourceClosure,
2903
2904
  publicationGeneration: context.generation,
@@ -2924,18 +2925,18 @@ async function buildParameterizedPackages(context) {
2924
2925
  const root = sourceSubject(resolved.value.rootPackageId);
2925
2926
  if (root === void 0) {
2926
2927
  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",
2928
+ code: "pack-parent-has-no-parameters",
2929
+ expected: "the instance parent chain to terminate at a ScriptablePack source",
2930
+ hint: "point the instance at a ScriptablePack *.pack.ts source with parameters",
2930
2931
  detail: { packageId: PackageId.format(subject.packageId) }
2931
2932
  });
2932
2933
  }
2933
- const loaded = await loadParameterizedScriptablePack(root.sourcePath);
2934
+ const loaded = await loadScriptablePack(root.sourcePath);
2934
2935
  if (!loaded.ok) dynamicFailure(context, loaded.error);
2935
2936
  if (PackageId.format(loaded.value.packageId) !== PackageId.format(root.packageId)) {
2936
2937
  dynamicFailure(context, {
2937
2938
  code: "pack-source-revision-conflict",
2938
- expected: "the parameterized parent packageId to remain fixed during production",
2939
+ expected: "the ScriptablePack parent packageId to remain fixed during production",
2939
2940
  hint: "retry after source writes settle and rebuild the current generation",
2940
2941
  detail: {
2941
2942
  sourcePath: root.sourcePath,
@@ -2947,7 +2948,7 @@ async function buildParameterizedPackages(context) {
2947
2948
  const packageId = PackageId.format(subject.packageId);
2948
2949
  inputs.push({
2949
2950
  sourcePath: subject.sourcePath,
2950
- displaySourcePath: parameterizedCatalogSourcePath(context, subject.sourcePath),
2951
+ displaySourcePath: packCatalogSourcePath(context, subject.sourcePath),
2951
2952
  definition: loaded.value,
2952
2953
  sourceClosure: root.sourceClosure,
2953
2954
  subjectPackageId: subject.packageId,
@@ -2976,7 +2977,7 @@ async function buildParameterizedPackages(context) {
2976
2977
  }
2977
2978
  );
2978
2979
  const availableGuids = new Set(requiredGuids.map((guid) => AssetGuid$1.format(guid).toLowerCase()));
2979
- const built = await produceParameterizedScriptablePackProducts({
2980
+ const built = await produceScriptablePackProducts({
2980
2981
  sources: inputs,
2981
2982
  declaredExternalOutputs: externalOutputs,
2982
2983
  availableGuids
@@ -2987,9 +2988,9 @@ async function buildParameterizedPackages(context) {
2987
2988
  const prepared = built.value.get(input.displaySourcePath);
2988
2989
  if (prepared === void 0) {
2989
2990
  dynamicFailure(context, {
2990
- code: "parameterized-pack-build-failed",
2991
+ code: "pack-build-failed",
2991
2992
  expected: "the worklist to return one prepared result per source subject",
2992
- hint: "rerun the parameterized Pack generation from a clean inventory",
2993
+ hint: "rerun Pack source generation from a clean inventory",
2993
2994
  detail: { sourcePath: input.sourcePath }
2994
2995
  });
2995
2996
  }
@@ -3105,13 +3106,13 @@ async function emitAuthoredPack(work, guidSeen, entry, availableGuids) {
3105
3106
  });
3106
3107
  }
3107
3108
  if (declaration.value.schemaVersion === "3.0.0") {
3108
- const parsed = parseParameterizedPackJson(declaration.value);
3109
+ const parsed = parsePackSourceJson(declaration.value);
3109
3110
  if (!parsed.ok) dynamicFailure(work.context, parsed.error);
3110
3111
  if (parsed.value.format !== "direct") {
3111
3112
  dynamicFailure(work.context, {
3112
3113
  code: "catalog-declaration-missing",
3113
3114
  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",
3115
+ hint: "instances are built from their ScriptablePack parent and do not have direct Catalog rows",
3115
3116
  detail: { stage: "scan", sourcePath: packPath }
3116
3117
  });
3117
3118
  }
@@ -3210,7 +3211,7 @@ async function emitAuthoredPack(work, guidSeen, entry, availableGuids) {
3210
3211
  guidSeen.add(guid.toLowerCase());
3211
3212
  }
3212
3213
  }
3213
- async function emitParameterizedPack(work, guidSeen, bundle) {
3214
+ async function emitScriptablePack(work, guidSeen, bundle) {
3214
3215
  const { input, prepared } = bundle;
3215
3216
  const packageId = PackageId.format(input.subjectPackageId ?? input.definition.packageId);
3216
3217
  const runtimePublication = createRuntimePackPublication({
@@ -3385,7 +3386,7 @@ async function emitBuildEntry(work, guidSeen, entry, availableGuids) {
3385
3386
  });
3386
3387
  }
3387
3388
  async function produceBuildAssets(context) {
3388
- const dynamicBundles = await buildParameterizedPackages(context);
3389
+ const dynamicBundles = await buildPackSources(context);
3389
3390
  const entries = [
3390
3391
  ...context.inventory.entries,
3391
3392
  ...dynamicBundles.flatMap((bundle) => bundle.entries)
@@ -3395,7 +3396,7 @@ async function produceBuildAssets(context) {
3395
3396
  const guidSeen = /* @__PURE__ */ new Set();
3396
3397
  const work = { importedEntries, context };
3397
3398
  for (const bundle of dynamicBundles) {
3398
- await emitParameterizedPack(work, guidSeen, bundle);
3399
+ await emitScriptablePack(work, guidSeen, bundle);
3399
3400
  }
3400
3401
  for (const entry of importedEntries) {
3401
3402
  if (!guidSeen.has(entry.guid.toLowerCase()))
@@ -4318,6 +4319,176 @@ function importPublicationFailure(error) {
4318
4319
  diagnostic: error
4319
4320
  };
4320
4321
  }
4322
+ function publicationArtifacts(transport) {
4323
+ return Object.fromEntries(
4324
+ (transport?.artifacts ?? []).map((artifact) => [
4325
+ artifact.path,
4326
+ { mediaType: artifact.mediaType, bytes: artifact.bytes }
4327
+ ])
4328
+ );
4329
+ }
4330
+ function publicationContext(input) {
4331
+ return {
4332
+ sourceMeta: "<import-publication>",
4333
+ anchorGuid: input.guid,
4334
+ affectedGuids: input.publishedGuids,
4335
+ producer: "source-package/import-publication",
4336
+ importer: "import-publication"
4337
+ };
4338
+ }
4339
+ function validatePublicationArtifactClosure(input) {
4340
+ const context = publicationContext(input);
4341
+ const pack = input.pack;
4342
+ if (pack === null || typeof pack !== "object" || pack.schemaVersion !== "2.0.0" || pack.kind !== "internal-text-package") {
4343
+ return ok(publicationArtifacts(input.transport));
4344
+ }
4345
+ const assets = pack.assets;
4346
+ if (!Array.isArray(assets)) {
4347
+ return err(
4348
+ sourcePackageError("source-package-publication-invalid", context, {
4349
+ stage: "route-integrity",
4350
+ reason: "published Pack does not contain an assets array"
4351
+ })
4352
+ );
4353
+ }
4354
+ const required = /* @__PURE__ */ new Map();
4355
+ for (const asset of assets) {
4356
+ if (asset === null || typeof asset !== "object") {
4357
+ return err(
4358
+ sourcePackageError("source-package-publication-invalid", context, {
4359
+ stage: "route-integrity",
4360
+ reason: "published Pack contains a non-object asset row"
4361
+ })
4362
+ );
4363
+ }
4364
+ const rawArtifacts = asset.artifacts;
4365
+ if (rawArtifacts === void 0) continue;
4366
+ if (rawArtifacts === null || typeof rawArtifacts !== "object" || Array.isArray(rawArtifacts)) {
4367
+ return err(
4368
+ sourcePackageError("source-package-publication-invalid", context, {
4369
+ stage: "route-integrity",
4370
+ reason: "published Pack contains an invalid asset artifact map"
4371
+ })
4372
+ );
4373
+ }
4374
+ for (const [localKey, rawDescriptor] of Object.entries(
4375
+ rawArtifacts
4376
+ )) {
4377
+ if (rawDescriptor === null || typeof rawDescriptor !== "object") {
4378
+ return err(
4379
+ sourcePackageError("source-package-publication-invalid", context, {
4380
+ stage: "route-integrity",
4381
+ reason: `artifact descriptor ${localKey} is not an object`
4382
+ })
4383
+ );
4384
+ }
4385
+ const descriptor = rawDescriptor;
4386
+ const path = descriptor.path;
4387
+ if (typeof path !== "string" || path.length === 0) {
4388
+ return err(
4389
+ sourcePackageError("source-package-publication-invalid", context, {
4390
+ stage: "route-integrity",
4391
+ reason: `artifact descriptor ${localKey} has no package-relative path`
4392
+ })
4393
+ );
4394
+ }
4395
+ const mediaType = descriptor.mediaType;
4396
+ const byteLength = descriptor.byteLength;
4397
+ const integrityValue = descriptor.integrity;
4398
+ const integrity = integrityValue !== null && typeof integrityValue === "object" ? {
4399
+ algorithm: integrityValue.algorithm,
4400
+ digest: integrityValue.digest
4401
+ } : void 0;
4402
+ 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")) {
4403
+ return err(
4404
+ sourcePackageError("source-package-publication-invalid", context, {
4405
+ stage: "route-integrity",
4406
+ reason: `artifact descriptor ${path} has invalid metadata`
4407
+ })
4408
+ );
4409
+ }
4410
+ if (required.has(path)) {
4411
+ return err(
4412
+ sourcePackageError("source-package-publication-invalid", context, {
4413
+ stage: "route-integrity",
4414
+ reason: `artifact path ${path} is declared more than once`
4415
+ })
4416
+ );
4417
+ }
4418
+ required.set(path, {
4419
+ ...typeof mediaType === "string" ? { mediaType } : {},
4420
+ ...typeof byteLength === "number" ? { byteLength } : {},
4421
+ ...integrity !== void 0 && typeof integrity.algorithm === "string" && typeof integrity.digest === "string" ? { integrity: { algorithm: integrity.algorithm, digest: integrity.digest } } : {}
4422
+ });
4423
+ }
4424
+ }
4425
+ const available = /* @__PURE__ */ new Map();
4426
+ const duplicatePaths = [];
4427
+ for (const artifact of input.transport?.artifacts ?? []) {
4428
+ if (available.has(artifact.path)) duplicatePaths.push(artifact.path);
4429
+ available.set(artifact.path, artifact);
4430
+ }
4431
+ const missing = [];
4432
+ const mismatched = [...duplicatePaths.map((path) => `${path}: duplicate body`)];
4433
+ for (const path of available.keys()) {
4434
+ if (!required.has(path)) mismatched.push(`${path}: unexpected body`);
4435
+ }
4436
+ for (const [path, descriptor] of required) {
4437
+ const artifact = available.get(path);
4438
+ if (artifact === void 0) {
4439
+ missing.push(path);
4440
+ continue;
4441
+ }
4442
+ if (!(artifact.bytes instanceof Uint8Array)) {
4443
+ mismatched.push(`${path}: body is not Uint8Array`);
4444
+ continue;
4445
+ }
4446
+ if (descriptor.mediaType !== void 0 && artifact.mediaType !== descriptor.mediaType) {
4447
+ mismatched.push(`${path}: media type mismatch`);
4448
+ }
4449
+ if (descriptor.byteLength !== void 0 && artifact.bytes.byteLength !== descriptor.byteLength) {
4450
+ mismatched.push(`${path}: byte length mismatch`);
4451
+ }
4452
+ if (descriptor.integrity !== void 0) {
4453
+ const actualDigest = `sha256:${createHash("sha256").update(artifact.bytes).digest("hex")}`;
4454
+ if (descriptor.integrity.algorithm !== "sha256" || descriptor.integrity.digest !== actualDigest) {
4455
+ mismatched.push(`${path}: integrity mismatch`);
4456
+ }
4457
+ }
4458
+ }
4459
+ if (missing.length > 0 || mismatched.length > 0) {
4460
+ return err(
4461
+ sourcePackageError("source-package-publication-invalid", context, {
4462
+ stage: "route-integrity",
4463
+ reason: "Pack artifact closure is incomplete or mismatched",
4464
+ ...missing.length === 0 ? {} : { missing },
4465
+ ...mismatched.length === 0 ? {} : { unexpected: mismatched }
4466
+ })
4467
+ );
4468
+ }
4469
+ if (input.transport !== void 0) {
4470
+ let transportedPack;
4471
+ try {
4472
+ transportedPack = JSON.parse(input.transport.body);
4473
+ } catch {
4474
+ return err(
4475
+ sourcePackageError("source-package-publication-invalid", context, {
4476
+ stage: "route-integrity",
4477
+ reason: "transport body is not valid JSON for the published Pack"
4478
+ })
4479
+ );
4480
+ }
4481
+ if (canonicalDdcJson(transportedPack) !== canonicalDdcJson(pack)) {
4482
+ return err(
4483
+ sourcePackageError("source-package-publication-invalid", context, {
4484
+ stage: "route-integrity",
4485
+ reason: "transport body does not match the published Pack"
4486
+ })
4487
+ );
4488
+ }
4489
+ }
4490
+ return ok(publicationArtifacts(input.transport));
4491
+ }
4321
4492
  function projectImportPublication(input, head, observedAt) {
4322
4493
  const digest3 = head.currentKey ?? input.desiredKey;
4323
4494
  const revision = { digest: digest3, observedAt, rootId: input.root };
@@ -4345,6 +4516,15 @@ async function publishImportPublication(input) {
4345
4516
  return commitImportPublication(staged.candidate);
4346
4517
  }
4347
4518
  async function stageImportPublication(input) {
4519
+ const validatedArtifacts = validatePublicationArtifactClosure(input);
4520
+ if (!validatedArtifacts.ok) {
4521
+ return {
4522
+ ok: false,
4523
+ error: importPublicationFailure(validatedArtifacts.error),
4524
+ head: await inspectHead(input.root, input.guid, input.desiredKey)
4525
+ };
4526
+ }
4527
+ const artifacts = validatedArtifacts.value;
4348
4528
  const staged = await stageSourcePackageDdc({
4349
4529
  root: input.root,
4350
4530
  entry: {
@@ -4352,7 +4532,7 @@ async function stageImportPublication(input) {
4352
4532
  guid: input.guid,
4353
4533
  payload: input.pack,
4354
4534
  refs: [],
4355
- artifacts: {},
4535
+ artifacts,
4356
4536
  receipt: {
4357
4537
  guid: input.guid,
4358
4538
  key: input.desiredKey,
@@ -4362,17 +4542,11 @@ async function stageImportPublication(input) {
4362
4542
  guid: input.guid,
4363
4543
  payload: input.pack,
4364
4544
  refs: [],
4365
- artifacts: {}
4545
+ artifacts
4366
4546
  })
4367
4547
  }
4368
4548
  },
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
- }
4549
+ context: publicationContext(input)
4376
4550
  });
4377
4551
  if (!staged.ok) {
4378
4552
  return {
@@ -4460,6 +4634,6 @@ async function restoreImportPublication(candidate) {
4460
4634
  await candidate.ddc.session.restoreEntry(candidate.ddc);
4461
4635
  }
4462
4636
 
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 };
4637
+ 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
4638
  //# sourceMappingURL=index.mjs.map
4465
4639
  //# sourceMappingURL=index.mjs.map