@forgeax/engine-pack 0.1.6 → 0.1.19

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 (37) hide show
  1. package/README.md +12 -1
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/build.d.ts +1 -1
  4. package/dist/build.d.ts.map +1 -1
  5. package/dist/build.mjs +100 -51
  6. package/dist/build.mjs.map +1 -1
  7. package/dist/catalog-builder.d.ts +12 -0
  8. package/dist/catalog-builder.d.ts.map +1 -1
  9. package/dist/cli-asset.mjs +1 -1
  10. package/dist/cli-asset.mjs.map +1 -1
  11. package/dist/evidence/material-cook.d.ts +28 -6
  12. package/dist/evidence/material-cook.d.ts.map +1 -1
  13. package/dist/index.d.ts +1 -1
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.mjs +97 -42
  16. package/dist/index.mjs.map +1 -1
  17. package/dist/material-cook.d.ts +1 -1
  18. package/dist/material-cook.d.ts.map +1 -1
  19. package/dist/material-cook.mjs +96 -41
  20. package/dist/material-cook.mjs.map +1 -1
  21. package/dist/scanner.mjs +1 -1
  22. package/dist/scanner.mjs.map +1 -1
  23. package/dist/scriptable-pack-node.d.ts.map +1 -1
  24. package/dist/scriptable-pack-node.mjs +1 -1
  25. package/dist/scriptable-pack-node.mjs.map +1 -1
  26. package/package.json +3 -3
  27. package/src/__tests__/material-cook-dependencies.unit.test.ts +111 -0
  28. package/src/__tests__/material-cook-receipt.unit.test.ts +77 -20
  29. package/src/__tests__/material-cook-schema.unit.test.ts +64 -10
  30. package/src/__tests__/pack-v2-fixture-migration.test.ts +24 -1
  31. package/src/build.ts +1 -0
  32. package/src/catalog-builder.ts +42 -5
  33. package/src/evidence/material-cook.ts +133 -54
  34. package/src/index.ts +4 -0
  35. package/src/material-cook.ts +2 -0
  36. package/src/schema/material-cook.schema.json +48 -8
  37. package/src/scriptable-pack-node.ts +4 -1
package/dist/build.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ok, err, catalogOperationsFor, authoringCapabilityForAssetKind, PACK_ERROR_HINTS, MATERIAL_TEXTURE_SLOTS, projectCookProductEvidence, projectAssetEvidence, validateSourceOverrideMap, catalogEntryDigest, AssetError, ImportError } from '@forgeax/engine-types';
2
- import { join, dirname, resolve, posix, basename, relative, extname } from 'path';
2
+ import { join, dirname, resolve, isAbsolute, posix, relative, basename, extname } from 'path';
3
3
  import { uuidv7obj } from 'uuidv7';
4
4
  import { readFileSync, existsSync } from 'fs';
5
5
  import { createHash } from 'crypto';
@@ -8552,7 +8552,7 @@ function buildTimeoutFailure(sourcePath, timeoutMs) {
8552
8552
  };
8553
8553
  }
8554
8554
  async function loadScriptablePack(sourcePath, options = {}) {
8555
- const timeoutMs = options.timeoutMs ?? 5e3;
8555
+ const timeoutMs = options.timeoutMs ?? 15e3;
8556
8556
  const buildTimeoutMs = options.buildTimeoutMs ?? 5e3;
8557
8557
  const executor = options.executor ?? new WorkerScriptablePackExecutor();
8558
8558
  let disposeReason;
@@ -9047,6 +9047,11 @@ async function scanInventory(roots, opts = {}) {
9047
9047
  function sourcePathFor(cwd, path) {
9048
9048
  return relative(cwd, path).replace(/\\/g, "/");
9049
9049
  }
9050
+ function catalogSourcePathFor(cwd, path, sourceIdentityFor) {
9051
+ const projected = sourceIdentityFor?.(path);
9052
+ const catalogPath = projected === void 0 || isAbsolute(projected) ? sourcePathFor(cwd, path) : projected;
9053
+ return catalogPath.replaceAll("\\", "/").replace(/^\.\//, "");
9054
+ }
9050
9055
  function metaPathForGuid(declarations, guid) {
9051
9056
  const lower = guid.toLowerCase();
9052
9057
  for (const [path, declaration] of declarations) {
@@ -9065,7 +9070,7 @@ function unsupportedPolicyError(path, importer, policy) {
9065
9070
  subjects: [path]
9066
9071
  };
9067
9072
  }
9068
- function projectMeta(rawPath, cwd, base, assetPaths, importerPolicy, sourceDeclaration) {
9073
+ function projectMeta(rawPath, cwd, base, assetPaths, importerPolicy, sourceDeclaration, sourceIdentityFor) {
9069
9074
  const meta = sourceDeclaration.value;
9070
9075
  const policy = importerPolicy(meta.importer);
9071
9076
  if (policy.disposition !== "publish") {
@@ -9082,7 +9087,7 @@ function projectMeta(rawPath, cwd, base, assetPaths, importerPolicy, sourceDecla
9082
9087
  }
9083
9088
  };
9084
9089
  }
9085
- const sourcePath = sourcePathFor(cwd, resolved.value);
9090
+ const sourcePath = catalogSourcePathFor(cwd, resolved.value, sourceIdentityFor);
9086
9091
  const packageUrl2 = `${base}/__forgeax-ddc/${meta.subAssets[0]?.guid?.toLowerCase() ?? "pack"}.pack.json`;
9087
9092
  const declaration = {
9088
9093
  importer: meta.importer,
@@ -9124,14 +9129,14 @@ function projectMeta(rawPath, cwd, base, assetPaths, importerPolicy, sourceDecla
9124
9129
  )
9125
9130
  };
9126
9131
  }
9127
- function projectSource(path, cwd, base, assetPaths, importerPolicy, visibility, sourceDeclaration, declarations) {
9132
+ function projectSource(path, cwd, base, assetPaths, importerPolicy, visibility, sourceDeclaration, declarations, sourceIdentityFor) {
9128
9133
  if (sourceDeclaration.format === "pack.ts") {
9129
9134
  const meta = { ...sourceDeclaration.meta, source: sourcePathFor(cwd, path) };
9130
9135
  const anchorGuid = meta.subAssets.map((asset) => asset.guid.toLowerCase()).sort()[0];
9131
9136
  return anchorGuid === void 0 ? { entries: [] } : {
9132
9137
  entries: projectExternalCatalogEntries(
9133
9138
  meta,
9134
- sourcePathFor(cwd, path),
9139
+ catalogSourcePathFor(cwd, path, sourceIdentityFor),
9135
9140
  `${base}/__forgeax-ddc/${anchorGuid}.pack.json`,
9136
9141
  meta.subAssets,
9137
9142
  (output) => deriveAssetName(path, meta.subAssets.length, output.name)
@@ -9147,12 +9152,20 @@ function projectSource(path, cwd, base, assetPaths, importerPolicy, visibility,
9147
9152
  }) === false) {
9148
9153
  return { entries: [] };
9149
9154
  }
9150
- const projected = projectMeta(path, cwd, base, assetPaths, importerPolicy, sourceDeclaration);
9155
+ const projected = projectMeta(
9156
+ path,
9157
+ cwd,
9158
+ base,
9159
+ assetPaths,
9160
+ importerPolicy,
9161
+ sourceDeclaration,
9162
+ sourceIdentityFor
9163
+ );
9151
9164
  if (projected.declaration !== void 0) declarations.set(path, projected.declaration);
9152
9165
  return projected;
9153
9166
  }
9154
9167
  const parsed = sourceDeclaration.value;
9155
- const sourcePath = sourcePathFor(cwd, path);
9168
+ const sourcePath = catalogSourcePathFor(cwd, path, sourceIdentityFor);
9156
9169
  const provenance = parsed.provenance ?? { provider: "pack", version: parsed.schemaVersion };
9157
9170
  return {
9158
9171
  entries: projectPackageCatalog(
@@ -9218,7 +9231,8 @@ async function buildCatalogProjection(roots, options) {
9218
9231
  options.importerPolicy,
9219
9232
  options.visibility,
9220
9233
  sourceDeclaration,
9221
- declarations
9234
+ declarations,
9235
+ options.sourceIdentityFor
9222
9236
  );
9223
9237
  entries.push(...projected.entries);
9224
9238
  if (projected.error !== void 0) errors.push(projected.error);
@@ -9547,77 +9561,112 @@ function serializeCookedMaterialRecord(record) {
9547
9561
  function serializeMaterialCookReceipt(receipt) {
9548
9562
  return JSON.stringify(jsonValue({ ...receipt, sourceClosure: unique(receipt.sourceClosure) }));
9549
9563
  }
9550
- function invalid2(field) {
9564
+ function invalid2(field, actual2) {
9551
9565
  return err({
9552
9566
  code: "material-cook-record-invalid",
9553
- expected: "a complete material-cook/2 record with derived layout identity",
9567
+ expected: "a complete material-cook/3 record with layered identity and provenance",
9554
9568
  hint: "re-cook the material and publish its record, artifact, references, and receipt together",
9555
- detail: { field }
9569
+ detail: {
9570
+ field,
9571
+ ...actual2 === void 0 ? {} : { actual: actual2 },
9572
+ action: "inspect the named field and recook the material generation"
9573
+ }
9574
+ });
9575
+ }
9576
+ var IDENTITY_FIELDS = [
9577
+ "materialContractDigest",
9578
+ "sourceRevision",
9579
+ "sourceClosureDigest",
9580
+ "layoutIdentity",
9581
+ "programIdentity",
9582
+ "pipelineIdentity",
9583
+ "materialPublicationIdentity",
9584
+ "cookIdentity",
9585
+ "compilerFingerprint",
9586
+ "artifactDigest"
9587
+ ];
9588
+ function isGeneration(value) {
9589
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 1;
9590
+ }
9591
+ function validateIdentity(value) {
9592
+ if (value === null || typeof value !== "object") return invalid2("receipt.identity", value);
9593
+ const candidate = value;
9594
+ for (const field of IDENTITY_FIELDS) {
9595
+ if (typeof candidate[field] !== "string" || candidate[field].length === 0) {
9596
+ return invalid2(`receipt.identity.${field}`, candidate[field]);
9597
+ }
9598
+ }
9599
+ if (candidate.wasm === null || typeof candidate.wasm !== "object") {
9600
+ return invalid2("receipt.identity.wasm", candidate.wasm);
9601
+ }
9602
+ const wasm = candidate.wasm;
9603
+ for (const field of ["sourceContentKey", "artifactSha256", "glueSha256"]) {
9604
+ if (typeof wasm[field] !== "string" || wasm[field].length === 0) {
9605
+ return invalid2(`receipt.identity.wasm.${field}`, wasm[field]);
9606
+ }
9607
+ }
9608
+ for (const field of ["valueGeneration", "dependencyGeneration", "cookGeneration"]) {
9609
+ if (!isGeneration(candidate[field]))
9610
+ return invalid2(`receipt.identity.${field}`, candidate[field]);
9611
+ }
9612
+ return ok({
9613
+ ...candidate,
9614
+ wasm
9556
9615
  });
9557
9616
  }
9558
9617
  function validateMaterialCookReceipt(value, expected = {}) {
9559
9618
  if (value === null || typeof value !== "object") return invalid2("receipt");
9560
9619
  const candidate = value;
9561
- if (candidate.schemaVersion !== "material-cook/2") return invalid2("receipt.schemaVersion");
9562
- if (typeof candidate.layoutIdentity !== "string" || candidate.layoutIdentity.length === 0) {
9563
- return invalid2("receipt.layoutIdentity");
9564
- }
9620
+ if (candidate.schemaVersion !== "material-cook/3")
9621
+ return invalid2("receipt.schemaVersion", candidate.schemaVersion);
9622
+ const identityResult = validateIdentity(candidate.identity);
9623
+ if (!identityResult.ok) return identityResult;
9624
+ const identity = identityResult.value;
9565
9625
  if (candidate.derivedInterface === null || typeof candidate.derivedInterface !== "object") {
9566
- return invalid2("receipt.derivedInterface");
9626
+ return invalid2("receipt.derivedInterface", candidate.derivedInterface);
9567
9627
  }
9568
9628
  const derivedInterface = candidate.derivedInterface;
9569
- if (derivedInterface.layoutIdentity !== candidate.layoutIdentity) {
9570
- return invalid2("receipt.derivedInterface.layoutIdentity");
9571
- }
9572
- for (const field of [
9573
- "sourceClosure",
9574
- "profile",
9575
- "compilerVersion",
9576
- "inputDigest",
9577
- "outputDigest"
9578
- ]) {
9629
+ if (derivedInterface.layoutIdentity !== identity.layoutIdentity) {
9630
+ return invalid2("receipt.derivedInterface.layoutIdentity", derivedInterface.layoutIdentity);
9631
+ }
9632
+ for (const field of ["sourceClosure", "profile", "compilerVersion"]) {
9579
9633
  const fieldValue = candidate[field];
9580
9634
  if (field === "sourceClosure" && !Array.isArray(fieldValue) || field !== "sourceClosure" && typeof fieldValue !== "string") {
9581
- return invalid2(`receipt.${field}`);
9635
+ return invalid2(`receipt.${field}`, fieldValue);
9582
9636
  }
9583
9637
  }
9584
9638
  const sourceClosure = candidate.sourceClosure;
9585
9639
  if (Array.isArray(sourceClosure) && sourceClosure.some((path) => typeof path !== "string")) {
9586
- return invalid2("receipt.sourceClosure");
9587
- }
9588
- if (expected.layoutIdentity !== void 0 && candidate.layoutIdentity !== expected.layoutIdentity) {
9589
- return invalid2("receipt.layoutIdentity");
9640
+ return invalid2("receipt.sourceClosure", sourceClosure);
9590
9641
  }
9591
- if (expected.artifactDigest !== void 0 && candidate.outputDigest !== expected.artifactDigest) {
9592
- return invalid2("receipt.outputDigest");
9642
+ if (expected.layoutIdentity !== void 0 && identity.layoutIdentity !== expected.layoutIdentity) {
9643
+ return invalid2("receipt.identity.layoutIdentity", identity.layoutIdentity);
9593
9644
  }
9594
- if (expected.inputDigest !== void 0 && candidate.inputDigest !== expected.inputDigest) {
9595
- return invalid2("receipt.inputDigest");
9645
+ if (expected.artifactDigest !== void 0 && identity.artifactDigest !== expected.artifactDigest) {
9646
+ return invalid2("receipt.identity.artifactDigest", identity.artifactDigest);
9596
9647
  }
9597
- if (candidate.publicationGeneration !== void 0 && (typeof candidate.publicationGeneration !== "number" || !Number.isSafeInteger(candidate.publicationGeneration) || candidate.publicationGeneration < 1)) {
9598
- return invalid2("receipt.publicationGeneration");
9648
+ if (expected.inputDigest !== void 0 && identity.cookIdentity !== expected.inputDigest) {
9649
+ return invalid2("receipt.identity.cookIdentity", identity.cookIdentity);
9599
9650
  }
9600
9651
  return ok({
9601
- schemaVersion: "material-cook/2",
9652
+ schemaVersion: "material-cook/3",
9602
9653
  sourceClosure: candidate.sourceClosure,
9603
9654
  profile: candidate.profile,
9604
9655
  compilerVersion: candidate.compilerVersion,
9605
- inputDigest: candidate.inputDigest,
9606
- outputDigest: candidate.outputDigest,
9607
- layoutIdentity: candidate.layoutIdentity,
9608
- derivedInterface: { layoutIdentity: derivedInterface.layoutIdentity },
9609
- ...candidate.publicationGeneration === void 0 ? {} : { publicationGeneration: candidate.publicationGeneration }
9656
+ identity,
9657
+ derivedInterface: { layoutIdentity: derivedInterface.layoutIdentity }
9610
9658
  });
9611
9659
  }
9612
9660
  function validateCookedMaterialRecord(value) {
9613
9661
  if (value === null || typeof value !== "object") return invalid2("record");
9614
9662
  const candidate = value;
9615
- if (candidate.schemaVersion !== "material-cook/2") return invalid2("schemaVersion");
9663
+ if (candidate.schemaVersion !== "material-cook/3")
9664
+ return invalid2("schemaVersion", candidate.schemaVersion);
9616
9665
  if (typeof candidate.guid !== "string" || !candidate.guid) return invalid2("guid");
9617
9666
  if (candidate.materialGuid !== void 0 && typeof candidate.materialGuid !== "string")
9618
9667
  return invalid2("materialGuid");
9619
- if (candidate.publicationGeneration !== void 0 && (typeof candidate.publicationGeneration !== "number" || !Number.isSafeInteger(candidate.publicationGeneration) || candidate.publicationGeneration < 1))
9620
- return invalid2("publicationGeneration");
9668
+ if (candidate.publicationGeneration !== void 0 && !isGeneration(candidate.publicationGeneration))
9669
+ return invalid2("publicationGeneration", candidate.publicationGeneration);
9621
9670
  if (candidate.specializationKey !== void 0 && typeof candidate.specializationKey !== "string")
9622
9671
  return invalid2("specializationKey");
9623
9672
  if (candidate.artifactDigest !== void 0 && typeof candidate.artifactDigest !== "string")
@@ -9649,9 +9698,9 @@ function validateCookedMaterialRecord(value) {
9649
9698
  });
9650
9699
  if (!receiptResult.ok) return receiptResult;
9651
9700
  if (candidate.artifactDigest !== void 0 && candidate.artifactDigest !== artifact.digest)
9652
- return invalid2("artifactDigest");
9653
- if (candidate.publicationGeneration !== void 0 && receiptResult.value.publicationGeneration !== candidate.publicationGeneration)
9654
- return invalid2("receipt.publicationGeneration");
9701
+ return invalid2("artifactDigest", candidate.artifactDigest);
9702
+ if (candidate.publicationGeneration !== void 0 && receiptResult.value.identity.cookGeneration !== candidate.publicationGeneration)
9703
+ return invalid2("receipt.identity.cookGeneration", receiptResult.value.identity.cookGeneration);
9655
9704
  const normalized = {
9656
9705
  ...candidate,
9657
9706
  artifact: {
@@ -10163,6 +10212,6 @@ function createRuntimePackPublication(input) {
10163
10212
  };
10164
10213
  }
10165
10214
 
10166
- export { MESH_BIN_DIGEST_BYTES, MESH_BIN_HEADER_V4_BYTES, MESH_BIN_PROJECTION_VERSION, MESH_BIN_VERSION, SCRIPTABLE_PACK_ASSET_KINDS, SCRIPTABLE_PACK_CAPABILITY_MANIFEST, STANDARD_SCRIPTABLE_PACK_SCAN_OPTIONS, buildCatalogProjection, buildOfflineAssetEvidence, calculateCatalogDelta, calculateTopologyDiff, catalogProjectionFor, collectMaterialCookRefs, createMaterialArtifactDigest, createRuntimePackPublication, currentProjectionFor, decodeMeshBinHeader, diffTopology, finalizePackageProduct, finalizePackageTransportSource, findReservedAssetKindConflict, isScriptablePackAssetKind, loadAssetConfig, metaPathForGuid, packageTransportRevision, packageVerification, parsePackV2, projectCookedMaterialRecord, projectCookedPackageEntry, projectExternalCatalogEntries, projectPackageCatalog, projectRuntimeCatalogRow, projectScriptablePackMeta, projectScriptablePackSceneComponents, resolveAssetSource, scanInventory, serializeCookedMaterialRecord, serializeMaterialCookReceipt, upgradeLegacyAuthoredPack, validateArtifactPath, validateCookedMaterialRecord, validateMaterialCookReceipt, validateMeta, validatePack, validatePackV2, validateProducerContract, validateProducerOutputs, validateScriptablePackDefinition, writeMeshBinHeader };
10215
+ export { MESH_BIN_DIGEST_BYTES, MESH_BIN_HEADER_V4_BYTES, MESH_BIN_PROJECTION_VERSION, MESH_BIN_VERSION, SCRIPTABLE_PACK_ASSET_KINDS, SCRIPTABLE_PACK_CAPABILITY_MANIFEST, STANDARD_SCRIPTABLE_PACK_SCAN_OPTIONS, buildCatalogProjection, buildOfflineAssetEvidence, calculateCatalogDelta, calculateTopologyDiff, catalogProjectionFor, catalogSourcePathFor, collectMaterialCookRefs, createMaterialArtifactDigest, createRuntimePackPublication, currentProjectionFor, decodeMeshBinHeader, diffTopology, finalizePackageProduct, finalizePackageTransportSource, findReservedAssetKindConflict, isScriptablePackAssetKind, loadAssetConfig, metaPathForGuid, packageTransportRevision, packageVerification, parsePackV2, projectCookedMaterialRecord, projectCookedPackageEntry, projectExternalCatalogEntries, projectPackageCatalog, projectRuntimeCatalogRow, projectScriptablePackMeta, projectScriptablePackSceneComponents, resolveAssetSource, scanInventory, serializeCookedMaterialRecord, serializeMaterialCookReceipt, upgradeLegacyAuthoredPack, validateArtifactPath, validateCookedMaterialRecord, validateMaterialCookReceipt, validateMeta, validatePack, validatePackV2, validateProducerContract, validateProducerOutputs, validateScriptablePackDefinition, writeMeshBinHeader };
10167
10216
  //# sourceMappingURL=build.mjs.map
10168
10217
  //# sourceMappingURL=build.mjs.map