@forgeax/engine-pack 0.0.0-dev.8d955ade1c79

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 (276) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +429 -0
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/__tests__/ai-recovery.unit.test.d.ts +2 -0
  5. package/dist/__tests__/ai-recovery.unit.test.d.ts.map +1 -0
  6. package/dist/__tests__/artifact-path.test.d.ts +2 -0
  7. package/dist/__tests__/artifact-path.test.d.ts.map +1 -0
  8. package/dist/__tests__/asset-evidence-error-hints.test.d.ts +2 -0
  9. package/dist/__tests__/asset-evidence-error-hints.test.d.ts.map +1 -0
  10. package/dist/__tests__/asset-evidence-lifecycle.test.d.ts +2 -0
  11. package/dist/__tests__/asset-evidence-lifecycle.test.d.ts.map +1 -0
  12. package/dist/__tests__/asset-evidence-schema.test.d.ts +2 -0
  13. package/dist/__tests__/asset-evidence-schema.test.d.ts.map +1 -0
  14. package/dist/__tests__/atlas-cli-region-mismatch.test.d.ts +2 -0
  15. package/dist/__tests__/atlas-cli-region-mismatch.test.d.ts.map +1 -0
  16. package/dist/__tests__/atlas-error-code-owner.test-d.d.ts +2 -0
  17. package/dist/__tests__/atlas-error-code-owner.test-d.d.ts.map +1 -0
  18. package/dist/__tests__/cli-asset-evidence.integration.test.d.ts +2 -0
  19. package/dist/__tests__/cli-asset-evidence.integration.test.d.ts.map +1 -0
  20. package/dist/__tests__/cli.unit.test.d.ts +2 -0
  21. package/dist/__tests__/cli.unit.test.d.ts.map +1 -0
  22. package/dist/__tests__/evidence-source-inventory.unit.test.d.ts +2 -0
  23. package/dist/__tests__/evidence-source-inventory.unit.test.d.ts.map +1 -0
  24. package/dist/__tests__/guid-collision.unit.test.d.ts +2 -0
  25. package/dist/__tests__/guid-collision.unit.test.d.ts.map +1 -0
  26. package/dist/__tests__/guid-validator-surface.unit.test.d.ts +2 -0
  27. package/dist/__tests__/guid-validator-surface.unit.test.d.ts.map +1 -0
  28. package/dist/__tests__/load-asset-config.test.d.ts +2 -0
  29. package/dist/__tests__/load-asset-config.test.d.ts.map +1 -0
  30. package/dist/__tests__/material-cook-dependencies.unit.test.d.ts +2 -0
  31. package/dist/__tests__/material-cook-dependencies.unit.test.d.ts.map +1 -0
  32. package/dist/__tests__/material-cook-receipt.unit.test.d.ts +2 -0
  33. package/dist/__tests__/material-cook-receipt.unit.test.d.ts.map +1 -0
  34. package/dist/__tests__/material-cook-schema.unit.test.d.ts +2 -0
  35. package/dist/__tests__/material-cook-schema.unit.test.d.ts.map +1 -0
  36. package/dist/__tests__/mesh-bin-consumer-surface.unit.test.d.ts +2 -0
  37. package/dist/__tests__/mesh-bin-consumer-surface.unit.test.d.ts.map +1 -0
  38. package/dist/__tests__/mesh-bin-contract.unit.test.d.ts +2 -0
  39. package/dist/__tests__/mesh-bin-contract.unit.test.d.ts.map +1 -0
  40. package/dist/__tests__/meta-schema-optional.test.d.ts +2 -0
  41. package/dist/__tests__/meta-schema-optional.test.d.ts.map +1 -0
  42. package/dist/__tests__/meta-source-overrides.unit.test.d.ts +2 -0
  43. package/dist/__tests__/meta-source-overrides.unit.test.d.ts.map +1 -0
  44. package/dist/__tests__/native-cooker-registry.test.d.ts +2 -0
  45. package/dist/__tests__/native-cooker-registry.test.d.ts.map +1 -0
  46. package/dist/__tests__/offline-evidence-artifact-verification-owner.test-d.d.ts +2 -0
  47. package/dist/__tests__/offline-evidence-artifact-verification-owner.test-d.d.ts.map +1 -0
  48. package/dist/__tests__/offline-evidence.integration.test.d.ts +2 -0
  49. package/dist/__tests__/offline-evidence.integration.test.d.ts.map +1 -0
  50. package/dist/__tests__/owner-chain.integration.test.d.ts +2 -0
  51. package/dist/__tests__/owner-chain.integration.test.d.ts.map +1 -0
  52. package/dist/__tests__/pack-v2-fixture-migration.test.d.ts +2 -0
  53. package/dist/__tests__/pack-v2-fixture-migration.test.d.ts.map +1 -0
  54. package/dist/__tests__/pack-v2-schema.test.d.ts +2 -0
  55. package/dist/__tests__/pack-v2-schema.test.d.ts.map +1 -0
  56. package/dist/__tests__/pack.unit.test.d.ts +2 -0
  57. package/dist/__tests__/pack.unit.test.d.ts.map +1 -0
  58. package/dist/__tests__/package-finalizer.contract.test.d.ts +2 -0
  59. package/dist/__tests__/package-finalizer.contract.test.d.ts.map +1 -0
  60. package/dist/__tests__/producer-contract-schema.unit.test.d.ts +2 -0
  61. package/dist/__tests__/producer-contract-schema.unit.test.d.ts.map +1 -0
  62. package/dist/__tests__/resolve-asset-source.test.d.ts +2 -0
  63. package/dist/__tests__/resolve-asset-source.test.d.ts.map +1 -0
  64. package/dist/__tests__/runtime-projection.unit.test.d.ts +2 -0
  65. package/dist/__tests__/runtime-projection.unit.test.d.ts.map +1 -0
  66. package/dist/__tests__/runtime.browser.test.d.ts +2 -0
  67. package/dist/__tests__/runtime.browser.test.d.ts.map +1 -0
  68. package/dist/__tests__/scanner-inventory.contract.test.d.ts +2 -0
  69. package/dist/__tests__/scanner-inventory.contract.test.d.ts.map +1 -0
  70. package/dist/__tests__/scanner-inventory.test.d.ts +2 -0
  71. package/dist/__tests__/scanner-inventory.test.d.ts.map +1 -0
  72. package/dist/__tests__/scanner-mount-cycle.test.d.ts +2 -0
  73. package/dist/__tests__/scanner-mount-cycle.test.d.ts.map +1 -0
  74. package/dist/__tests__/scriptable-pack-cli.integration.test.d.ts +2 -0
  75. package/dist/__tests__/scriptable-pack-cli.integration.test.d.ts.map +1 -0
  76. package/dist/__tests__/scriptable-pack-ddc-key.unit.test.d.ts +2 -0
  77. package/dist/__tests__/scriptable-pack-ddc-key.unit.test.d.ts.map +1 -0
  78. package/dist/__tests__/scriptable-pack.test-d.d.ts +2 -0
  79. package/dist/__tests__/scriptable-pack.test-d.d.ts.map +1 -0
  80. package/dist/__tests__/scriptable-pack.unit.test.d.ts +2 -0
  81. package/dist/__tests__/scriptable-pack.unit.test.d.ts.map +1 -0
  82. package/dist/__tests__/topology-actions.unit.test.d.ts +2 -0
  83. package/dist/__tests__/topology-actions.unit.test.d.ts.map +1 -0
  84. package/dist/__tests__/topology.unit.test.d.ts +2 -0
  85. package/dist/__tests__/topology.unit.test.d.ts.map +1 -0
  86. package/dist/artifact-path.d.ts +9 -0
  87. package/dist/artifact-path.d.ts.map +1 -0
  88. package/dist/artifact-path.mjs +53 -0
  89. package/dist/artifact-path.mjs.map +1 -0
  90. package/dist/atlas/run-atlas.d.ts +8 -0
  91. package/dist/atlas/run-atlas.d.ts.map +1 -0
  92. package/dist/atlas/shelf-pack.d.ts +55 -0
  93. package/dist/atlas/shelf-pack.d.ts.map +1 -0
  94. package/dist/bridge.d.ts +2 -0
  95. package/dist/bridge.d.ts.map +1 -0
  96. package/dist/bridge.mjs +3 -0
  97. package/dist/bridge.mjs.map +1 -0
  98. package/dist/build.d.ts +19 -0
  99. package/dist/build.d.ts.map +1 -0
  100. package/dist/build.mjs +10203 -0
  101. package/dist/build.mjs.map +1 -0
  102. package/dist/builtin.d.ts +44 -0
  103. package/dist/builtin.d.ts.map +1 -0
  104. package/dist/builtin.mjs +141 -0
  105. package/dist/builtin.mjs.map +1 -0
  106. package/dist/catalog-builder.d.ts +43 -0
  107. package/dist/catalog-builder.d.ts.map +1 -0
  108. package/dist/catalog-delta.d.ts +11 -0
  109. package/dist/catalog-delta.d.ts.map +1 -0
  110. package/dist/catalog-projection.d.ts +91 -0
  111. package/dist/catalog-projection.d.ts.map +1 -0
  112. package/dist/cli-asset.d.ts +22 -0
  113. package/dist/cli-asset.d.ts.map +1 -0
  114. package/dist/cli-asset.mjs +9697 -0
  115. package/dist/cli-asset.mjs.map +1 -0
  116. package/dist/config.d.ts +6 -0
  117. package/dist/config.d.ts.map +1 -0
  118. package/dist/config.mjs +29 -0
  119. package/dist/config.mjs.map +1 -0
  120. package/dist/deriveAssetName.d.ts +15 -0
  121. package/dist/deriveAssetName.d.ts.map +1 -0
  122. package/dist/errors.d.ts +30 -0
  123. package/dist/errors.d.ts.map +1 -0
  124. package/dist/errors.mjs +19 -0
  125. package/dist/errors.mjs.map +1 -0
  126. package/dist/evidence/material-cook.d.ts +92 -0
  127. package/dist/evidence/material-cook.d.ts.map +1 -0
  128. package/dist/evidence/offline-evidence.d.ts +25 -0
  129. package/dist/evidence/offline-evidence.d.ts.map +1 -0
  130. package/dist/evidence/source-inventory.d.ts +29 -0
  131. package/dist/evidence/source-inventory.d.ts.map +1 -0
  132. package/dist/guid.d.ts +45 -0
  133. package/dist/guid.d.ts.map +1 -0
  134. package/dist/guid.mjs +94 -0
  135. package/dist/guid.mjs.map +1 -0
  136. package/dist/index.d.ts +15 -0
  137. package/dist/index.d.ts.map +1 -0
  138. package/dist/index.mjs +8612 -0
  139. package/dist/index.mjs.map +1 -0
  140. package/dist/material/artifact-writer.d.ts +14 -0
  141. package/dist/material/artifact-writer.d.ts.map +1 -0
  142. package/dist/material-cook.d.ts +2 -0
  143. package/dist/material-cook.d.ts.map +1 -0
  144. package/dist/material-cook.mjs +248 -0
  145. package/dist/material-cook.mjs.map +1 -0
  146. package/dist/mesh-bin-contract.d.ts +36 -0
  147. package/dist/mesh-bin-contract.d.ts.map +1 -0
  148. package/dist/mesh-bin-contract.mjs +96 -0
  149. package/dist/mesh-bin-contract.mjs.map +1 -0
  150. package/dist/name.mjs +22 -0
  151. package/dist/name.mjs.map +1 -0
  152. package/dist/native-cooker-registry.d.ts +47 -0
  153. package/dist/native-cooker-registry.d.ts.map +1 -0
  154. package/dist/native-cooker.d.ts +3 -0
  155. package/dist/native-cooker.d.ts.map +1 -0
  156. package/dist/native-cooker.mjs +142 -0
  157. package/dist/native-cooker.mjs.map +1 -0
  158. package/dist/package-finalizer.d.ts +121 -0
  159. package/dist/package-finalizer.d.ts.map +1 -0
  160. package/dist/producer-contract.d.ts +19 -0
  161. package/dist/producer-contract.d.ts.map +1 -0
  162. package/dist/resolve-asset-source.d.ts +4 -0
  163. package/dist/resolve-asset-source.d.ts.map +1 -0
  164. package/dist/resolve-asset-source.mjs +109 -0
  165. package/dist/resolve-asset-source.mjs.map +1 -0
  166. package/dist/runtime-projection.d.ts +14 -0
  167. package/dist/runtime-projection.d.ts.map +1 -0
  168. package/dist/runtime-publication.d.ts +44 -0
  169. package/dist/runtime-publication.d.ts.map +1 -0
  170. package/dist/runtime.d.ts +8 -0
  171. package/dist/runtime.d.ts.map +1 -0
  172. package/dist/runtime.mjs +7261 -0
  173. package/dist/runtime.mjs.map +1 -0
  174. package/dist/scanner.d.ts +113 -0
  175. package/dist/scanner.d.ts.map +1 -0
  176. package/dist/scanner.mjs +8819 -0
  177. package/dist/scanner.mjs.map +1 -0
  178. package/dist/schema-compiled.d.ts +12 -0
  179. package/dist/schema-compiled.d.ts.map +1 -0
  180. package/dist/schema.mjs +7369 -0
  181. package/dist/schema.mjs.map +1 -0
  182. package/dist/scriptable-pack-node.d.ts +62 -0
  183. package/dist/scriptable-pack-node.d.ts.map +1 -0
  184. package/dist/scriptable-pack-node.mjs +1674 -0
  185. package/dist/scriptable-pack-node.mjs.map +1 -0
  186. package/dist/scriptable-pack-worker.d.ts +2 -0
  187. package/dist/scriptable-pack-worker.d.ts.map +1 -0
  188. package/dist/scriptable-pack-worker.mjs +224 -0
  189. package/dist/scriptable-pack-worker.mjs.map +1 -0
  190. package/dist/scriptable-pack.d.ts +558 -0
  191. package/dist/scriptable-pack.d.ts.map +1 -0
  192. package/dist/scriptable-pack.mjs +672 -0
  193. package/dist/scriptable-pack.mjs.map +1 -0
  194. package/dist/topology.d.ts +10 -0
  195. package/dist/topology.d.ts.map +1 -0
  196. package/package.json +154 -0
  197. package/schema/meta.schema.json +173 -0
  198. package/schema/pack.schema.json +232 -0
  199. package/src/__tests__/ai-recovery.unit.test.ts +114 -0
  200. package/src/__tests__/artifact-path.test.ts +41 -0
  201. package/src/__tests__/asset-evidence-error-hints.test.ts +46 -0
  202. package/src/__tests__/asset-evidence-lifecycle.test.ts +104 -0
  203. package/src/__tests__/asset-evidence-schema.test.ts +86 -0
  204. package/src/__tests__/atlas-cli-region-mismatch.test.ts +134 -0
  205. package/src/__tests__/atlas-error-code-owner.test-d.ts +23 -0
  206. package/src/__tests__/cli-asset-evidence.integration.test.ts +172 -0
  207. package/src/__tests__/cli.unit.test.ts +448 -0
  208. package/src/__tests__/evidence-source-inventory.unit.test.ts +37 -0
  209. package/src/__tests__/guid-collision.unit.test.ts +112 -0
  210. package/src/__tests__/guid-validator-surface.unit.test.ts +20 -0
  211. package/src/__tests__/load-asset-config.test.ts +121 -0
  212. package/src/__tests__/material-cook-dependencies.unit.test.ts +112 -0
  213. package/src/__tests__/material-cook-receipt.unit.test.ts +148 -0
  214. package/src/__tests__/material-cook-schema.unit.test.ts +152 -0
  215. package/src/__tests__/mesh-bin-consumer-surface.unit.test.ts +22 -0
  216. package/src/__tests__/mesh-bin-contract.unit.test.ts +32 -0
  217. package/src/__tests__/meta-schema-optional.test.ts +116 -0
  218. package/src/__tests__/meta-source-overrides.unit.test.ts +71 -0
  219. package/src/__tests__/native-cooker-registry.test.ts +64 -0
  220. package/src/__tests__/offline-evidence-artifact-verification-owner.test-d.ts +64 -0
  221. package/src/__tests__/offline-evidence.integration.test.ts +106 -0
  222. package/src/__tests__/owner-chain.integration.test.ts +78 -0
  223. package/src/__tests__/pack-v2-fixture-migration.test.ts +87 -0
  224. package/src/__tests__/pack-v2-schema.test.ts +142 -0
  225. package/src/__tests__/pack.unit.test.ts +2218 -0
  226. package/src/__tests__/package-finalizer.contract.test.ts +105 -0
  227. package/src/__tests__/producer-contract-schema.unit.test.ts +92 -0
  228. package/src/__tests__/resolve-asset-source.test.ts +121 -0
  229. package/src/__tests__/runtime-projection.unit.test.ts +87 -0
  230. package/src/__tests__/runtime.browser.test.ts +15 -0
  231. package/src/__tests__/scanner-inventory.contract.test.ts +167 -0
  232. package/src/__tests__/scanner-inventory.test.ts +76 -0
  233. package/src/__tests__/scanner-mount-cycle.test.ts +232 -0
  234. package/src/__tests__/scriptable-pack-cli.integration.test.ts +47 -0
  235. package/src/__tests__/scriptable-pack-ddc-key.unit.test.ts +63 -0
  236. package/src/__tests__/scriptable-pack.test-d.ts +131 -0
  237. package/src/__tests__/scriptable-pack.unit.test.ts +789 -0
  238. package/src/__tests__/topology-actions.unit.test.ts +94 -0
  239. package/src/__tests__/topology.unit.test.ts +85 -0
  240. package/src/artifact-path.ts +69 -0
  241. package/src/atlas/run-atlas.ts +358 -0
  242. package/src/atlas/shelf-pack.ts +172 -0
  243. package/src/atlas/upng-ambient.d.ts +13 -0
  244. package/src/bridge.ts +2 -0
  245. package/src/build.ts +139 -0
  246. package/src/builtin.ts +117 -0
  247. package/src/catalog-builder.ts +313 -0
  248. package/src/catalog-delta.ts +189 -0
  249. package/src/catalog-projection.ts +344 -0
  250. package/src/cli-asset.ts +586 -0
  251. package/src/config.ts +36 -0
  252. package/src/deriveAssetName.ts +42 -0
  253. package/src/errors.ts +47 -0
  254. package/src/evidence/material-cook.ts +411 -0
  255. package/src/evidence/offline-evidence.ts +90 -0
  256. package/src/evidence/source-inventory.ts +193 -0
  257. package/src/guid.ts +99 -0
  258. package/src/index.ts +108 -0
  259. package/src/material/artifact-writer.ts +26 -0
  260. package/src/material-cook.ts +15 -0
  261. package/src/mesh-bin-contract.ts +150 -0
  262. package/src/native-cooker-registry.ts +235 -0
  263. package/src/native-cooker.ts +2 -0
  264. package/src/package-finalizer.ts +394 -0
  265. package/src/producer-contract.ts +277 -0
  266. package/src/resolve-asset-source.ts +88 -0
  267. package/src/runtime-projection.ts +100 -0
  268. package/src/runtime-publication.ts +190 -0
  269. package/src/runtime.ts +23 -0
  270. package/src/scanner.ts +715 -0
  271. package/src/schema/material-cook.schema.json +119 -0
  272. package/src/schema-compiled.ts +238 -0
  273. package/src/scriptable-pack-node.ts +1394 -0
  274. package/src/scriptable-pack-worker.ts +308 -0
  275. package/src/scriptable-pack.ts +1006 -0
  276. package/src/topology.ts +157 -0
@@ -0,0 +1,14 @@
1
+ export interface MaterialArtifactWriteInput {
2
+ readonly key: string;
3
+ readonly bytes: Uint8Array;
4
+ readonly mediaType?: string;
5
+ }
6
+ export interface MaterialArtifactWriteResult {
7
+ readonly key: string;
8
+ readonly bytes: Uint8Array;
9
+ readonly mediaType: string;
10
+ readonly digest: string;
11
+ }
12
+ /** Pack owns the immutable cooked material artifact tuple. */
13
+ export declare function writeMaterialArtifact(input: MaterialArtifactWriteInput): MaterialArtifactWriteResult;
14
+ //# sourceMappingURL=artifact-writer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact-writer.d.ts","sourceRoot":"","sources":["../../src/material/artifact-writer.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,8DAA8D;AAC9D,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,0BAA0B,GAChC,2BAA2B,CAO7B"}
@@ -0,0 +1,2 @@
1
+ export { type CookedMaterialRecord, collectMaterialCookRefs, createMaterialArtifactDigest, createMaterialCookIdentity, type MaterialCookArtifact, type MaterialCookReceipt, type MaterialCookRecordError, type MaterialCookRefs, type MaterialCookWasmProvenance, projectCookedMaterialRecord, serializeCookedMaterialRecord, serializeMaterialCookReceipt, validateCookedMaterialRecord, } from './evidence/material-cook.js';
2
+ //# sourceMappingURL=material-cook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"material-cook.d.ts","sourceRoot":"","sources":["../src/material-cook.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,oBAAoB,EACzB,uBAAuB,EACvB,4BAA4B,EAC5B,0BAA0B,EAC1B,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,uBAAuB,EAC5B,KAAK,gBAAgB,EACrB,KAAK,0BAA0B,EAC/B,2BAA2B,EAC3B,6BAA6B,EAC7B,4BAA4B,EAC5B,4BAA4B,GAC7B,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,248 @@
1
+ import { MATERIAL_TEXTURE_SLOTS, ok, err } from '@forgeax/engine-types';
2
+ import { sha256 } from '@noble/hashes/sha2.js';
3
+ import { bytesToHex } from '@noble/hashes/utils.js';
4
+
5
+ // src/evidence/material-cook.ts
6
+ function unique(values) {
7
+ return [...new Set(values)].sort();
8
+ }
9
+ function guidText(value) {
10
+ return typeof value === "string" ? value : Array.from(value, (byte) => byte.toString(16).padStart(2, "0")).join("");
11
+ }
12
+ function cookGuidText(value) {
13
+ return typeof value === "number" ? void 0 : guidText(value);
14
+ }
15
+ function textureValues(values, textureFields) {
16
+ return Object.entries(values ?? {}).flatMap(([name, value]) => {
17
+ if (value === null) return [];
18
+ if (typeof value === "string") {
19
+ return textureFields.has(name) ? [{ texture: value }] : [];
20
+ }
21
+ return value !== null && typeof value === "object" && !Array.isArray(value) && "texture" in value ? [value] : [];
22
+ });
23
+ }
24
+ function collectMaterialCookRefs(material) {
25
+ const textureFields = material.parameters === void 0 ? new Set(MATERIAL_TEXTURE_SLOTS) : new Set(
26
+ material.parameters.filter((parameter) => parameter.type === "texture").map((parameter) => parameter.name)
27
+ );
28
+ const textures = textureValues(material.values, textureFields);
29
+ return {
30
+ parent: material.parent ? [guidText(material.parent)] : [],
31
+ textures: unique(
32
+ textures.flatMap((value) => {
33
+ const guid = cookGuidText(value.texture);
34
+ return guid === void 0 ? [] : [guid];
35
+ })
36
+ ),
37
+ samplers: unique(
38
+ textures.flatMap((value) => {
39
+ if (value.sampler === void 0) return [];
40
+ const guid = cookGuidText(value.sampler);
41
+ return guid === void 0 ? [] : [guid];
42
+ })
43
+ ),
44
+ modules: unique((material.passes ?? []).map((pass) => pass.program.module))
45
+ };
46
+ }
47
+ function createMaterialArtifactDigest(bytes) {
48
+ return `sha256:${bytesToHex(sha256(bytes))}`;
49
+ }
50
+ function jsonValue(value) {
51
+ if (value instanceof Uint8Array) return [...value];
52
+ if (Array.isArray(value)) return value.map(jsonValue);
53
+ if (value !== null && typeof value === "object") {
54
+ return Object.fromEntries(
55
+ Object.entries(value).filter(([, entry]) => entry !== void 0).sort(([a], [b]) => a.localeCompare(b)).map(([key, entry]) => [key, jsonValue(entry)])
56
+ );
57
+ }
58
+ return value;
59
+ }
60
+ function createMaterialCookIdentity(input) {
61
+ const cookIdentity = createMaterialArtifactDigest(
62
+ new TextEncoder().encode(
63
+ JSON.stringify(
64
+ jsonValue({
65
+ materialContractDigest: input.materialContractDigest,
66
+ sourceRevision: input.sourceRevision,
67
+ sourceClosureDigest: input.sourceClosureDigest,
68
+ layoutIdentity: input.layoutIdentity,
69
+ programIdentity: input.programIdentity,
70
+ pipelineIdentity: input.pipelineIdentity,
71
+ compilerFingerprint: input.compilerFingerprint,
72
+ wasm: input.wasm,
73
+ artifactDigest: input.artifactDigest
74
+ })
75
+ )
76
+ )
77
+ );
78
+ return { ...input, cookIdentity };
79
+ }
80
+ function serializeCookedMaterialRecord(record) {
81
+ return JSON.stringify(jsonValue(record));
82
+ }
83
+ function serializeMaterialCookReceipt(receipt) {
84
+ return JSON.stringify(jsonValue({ ...receipt, sourceClosure: unique(receipt.sourceClosure) }));
85
+ }
86
+ function invalid(field, actual) {
87
+ return err({
88
+ code: "material-cook-record-invalid",
89
+ expected: "a complete material-cook/3 record with layered identity and provenance",
90
+ hint: "re-cook the material and publish its record, artifact, references, and receipt together",
91
+ detail: {
92
+ field,
93
+ ...actual === void 0 ? {} : { actual },
94
+ action: "inspect the named field and recook the material generation"
95
+ }
96
+ });
97
+ }
98
+ var IDENTITY_FIELDS = [
99
+ "materialContractDigest",
100
+ "sourceRevision",
101
+ "sourceClosureDigest",
102
+ "layoutIdentity",
103
+ "programIdentity",
104
+ "pipelineIdentity",
105
+ "materialPublicationIdentity",
106
+ "cookIdentity",
107
+ "compilerFingerprint",
108
+ "artifactDigest"
109
+ ];
110
+ function isGeneration(value) {
111
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 1;
112
+ }
113
+ function validateIdentity(value) {
114
+ if (value === null || typeof value !== "object") return invalid("receipt.identity", value);
115
+ const candidate = value;
116
+ for (const field of IDENTITY_FIELDS) {
117
+ if (typeof candidate[field] !== "string" || candidate[field].length === 0) {
118
+ return invalid(`receipt.identity.${field}`, candidate[field]);
119
+ }
120
+ }
121
+ if (candidate.wasm === null || typeof candidate.wasm !== "object") {
122
+ return invalid("receipt.identity.wasm", candidate.wasm);
123
+ }
124
+ const wasm = candidate.wasm;
125
+ for (const field of ["sourceContentKey", "artifactSha256", "glueSha256"]) {
126
+ if (typeof wasm[field] !== "string" || wasm[field].length === 0) {
127
+ return invalid(`receipt.identity.wasm.${field}`, wasm[field]);
128
+ }
129
+ }
130
+ for (const field of ["valueGeneration", "dependencyGeneration", "cookGeneration"]) {
131
+ if (!isGeneration(candidate[field]))
132
+ return invalid(`receipt.identity.${field}`, candidate[field]);
133
+ }
134
+ return ok({
135
+ ...candidate,
136
+ wasm
137
+ });
138
+ }
139
+ function validateMaterialCookReceipt(value, expected = {}) {
140
+ if (value === null || typeof value !== "object") return invalid("receipt");
141
+ const candidate = value;
142
+ if (candidate.schemaVersion !== "material-cook/3")
143
+ return invalid("receipt.schemaVersion", candidate.schemaVersion);
144
+ const identityResult = validateIdentity(candidate.identity);
145
+ if (!identityResult.ok) return identityResult;
146
+ const identity = identityResult.value;
147
+ if (candidate.derivedInterface === null || typeof candidate.derivedInterface !== "object") {
148
+ return invalid("receipt.derivedInterface", candidate.derivedInterface);
149
+ }
150
+ const derivedInterface = candidate.derivedInterface;
151
+ if (derivedInterface.layoutIdentity !== identity.layoutIdentity) {
152
+ return invalid("receipt.derivedInterface.layoutIdentity", derivedInterface.layoutIdentity);
153
+ }
154
+ for (const field of ["sourceClosure", "profile", "compilerVersion"]) {
155
+ const fieldValue = candidate[field];
156
+ if (field === "sourceClosure" && !Array.isArray(fieldValue) || field !== "sourceClosure" && typeof fieldValue !== "string") {
157
+ return invalid(`receipt.${field}`, fieldValue);
158
+ }
159
+ }
160
+ const sourceClosure = candidate.sourceClosure;
161
+ if (Array.isArray(sourceClosure) && sourceClosure.some((path) => typeof path !== "string")) {
162
+ return invalid("receipt.sourceClosure", sourceClosure);
163
+ }
164
+ if (expected.layoutIdentity !== void 0 && identity.layoutIdentity !== expected.layoutIdentity) {
165
+ return invalid("receipt.identity.layoutIdentity", identity.layoutIdentity);
166
+ }
167
+ if (expected.artifactDigest !== void 0 && identity.artifactDigest !== expected.artifactDigest) {
168
+ return invalid("receipt.identity.artifactDigest", identity.artifactDigest);
169
+ }
170
+ if (expected.inputDigest !== void 0 && identity.cookIdentity !== expected.inputDigest) {
171
+ return invalid("receipt.identity.cookIdentity", identity.cookIdentity);
172
+ }
173
+ return ok({
174
+ schemaVersion: "material-cook/3",
175
+ sourceClosure: candidate.sourceClosure,
176
+ profile: candidate.profile,
177
+ compilerVersion: candidate.compilerVersion,
178
+ identity,
179
+ derivedInterface: { layoutIdentity: derivedInterface.layoutIdentity }
180
+ });
181
+ }
182
+ function validateCookedMaterialRecord(value) {
183
+ if (value === null || typeof value !== "object") return invalid("record");
184
+ const candidate = value;
185
+ if (candidate.schemaVersion !== "material-cook/3")
186
+ return invalid("schemaVersion", candidate.schemaVersion);
187
+ if (typeof candidate.guid !== "string" || !candidate.guid) return invalid("guid");
188
+ if (candidate.materialGuid !== void 0 && typeof candidate.materialGuid !== "string")
189
+ return invalid("materialGuid");
190
+ if (candidate.publicationGeneration !== void 0 && !isGeneration(candidate.publicationGeneration))
191
+ return invalid("publicationGeneration", candidate.publicationGeneration);
192
+ if (candidate.specializationKey !== void 0 && typeof candidate.specializationKey !== "string")
193
+ return invalid("specializationKey");
194
+ if (candidate.artifactDigest !== void 0 && typeof candidate.artifactDigest !== "string")
195
+ return invalid("artifactDigest");
196
+ if (candidate.sourceClosure !== void 0 && (!Array.isArray(candidate.sourceClosure) || candidate.sourceClosure.some((path) => typeof path !== "string")))
197
+ return invalid("sourceClosure");
198
+ if (candidate.parameterContract !== void 0) {
199
+ if (candidate.parameterContract === null || typeof candidate.parameterContract !== "object")
200
+ return invalid("parameterContract");
201
+ const parameterContract = candidate.parameterContract;
202
+ if (!Array.isArray(parameterContract.parameters))
203
+ return invalid("parameterContract.parameters");
204
+ if (parameterContract.values === null || typeof parameterContract.values !== "object" || Array.isArray(parameterContract.values))
205
+ return invalid("parameterContract.values");
206
+ }
207
+ if (candidate.resolved === null || typeof candidate.resolved !== "object")
208
+ return invalid("resolved");
209
+ if (candidate.refs === null || typeof candidate.refs !== "object") return invalid("refs");
210
+ if (candidate.artifact === null || typeof candidate.artifact !== "object")
211
+ return invalid("artifact");
212
+ if (candidate.receipt === null || typeof candidate.receipt !== "object")
213
+ return invalid("receipt");
214
+ const artifact = candidate.artifact;
215
+ if (typeof artifact.digest !== "string" || !Array.isArray(artifact.bytes) && !ArrayBuffer.isView(artifact.bytes)) {
216
+ return invalid("artifact");
217
+ }
218
+ const receiptResult = validateMaterialCookReceipt(candidate.receipt, {
219
+ artifactDigest: artifact.digest
220
+ });
221
+ if (!receiptResult.ok) return receiptResult;
222
+ if (candidate.artifactDigest !== void 0 && candidate.artifactDigest !== artifact.digest)
223
+ return invalid("artifactDigest", candidate.artifactDigest);
224
+ if (candidate.publicationGeneration !== void 0 && receiptResult.value.identity.cookGeneration !== candidate.publicationGeneration)
225
+ return invalid("receipt.identity.cookGeneration", receiptResult.value.identity.cookGeneration);
226
+ const normalized = {
227
+ ...candidate,
228
+ artifact: {
229
+ ...artifact,
230
+ bytes: ArrayBuffer.isView(artifact.bytes) ? Uint8Array.from(artifact.bytes) : Uint8Array.from(artifact.bytes)
231
+ },
232
+ receipt: receiptResult.value
233
+ };
234
+ return ok(normalized);
235
+ }
236
+ function projectCookedMaterialRecord(record) {
237
+ return {
238
+ resolved: record.resolved,
239
+ refs: record.refs,
240
+ artifact: record.artifact,
241
+ receipt: record.receipt,
242
+ schemaVersion: record.schemaVersion
243
+ };
244
+ }
245
+
246
+ export { collectMaterialCookRefs, createMaterialArtifactDigest, createMaterialCookIdentity, projectCookedMaterialRecord, serializeCookedMaterialRecord, serializeMaterialCookReceipt, validateCookedMaterialRecord };
247
+ //# sourceMappingURL=material-cook.mjs.map
248
+ //# sourceMappingURL=material-cook.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/evidence/material-cook.ts"],"names":[],"mappings":"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","file":"material-cook.mjs","sourcesContent":["import type {\n MaterialAsset,\n MaterialParameter,\n MaterialPass,\n MaterialTextureReference,\n MaterialTextureValue,\n MaterialValue,\n Result,\n} from '@forgeax/engine-types';\nimport { err, MATERIAL_TEXTURE_SLOTS, ok } from '@forgeax/engine-types';\nimport { sha256 } from '@noble/hashes/sha2.js';\nimport { bytesToHex } from '@noble/hashes/utils.js';\n\nexport interface MaterialCookRefs {\n readonly parent: readonly string[];\n readonly textures: readonly string[];\n readonly samplers: readonly string[];\n readonly modules: readonly string[];\n}\n\nexport interface MaterialCookArtifact {\n readonly mediaType: string;\n readonly path: string;\n readonly digest: string;\n readonly bytes: Uint8Array;\n}\n\nexport interface MaterialCookWasmProvenance {\n readonly sourceContentKey: string;\n readonly artifactSha256: string;\n readonly glueSha256: string;\n}\n\nexport interface MaterialCookIdentity {\n readonly materialContractDigest: string;\n readonly sourceRevision: string;\n readonly sourceClosureDigest: string;\n readonly layoutIdentity: string;\n readonly programIdentity: string;\n readonly pipelineIdentity: string;\n readonly materialPublicationIdentity: string;\n readonly cookIdentity: string;\n readonly compilerFingerprint: string;\n readonly wasm: MaterialCookWasmProvenance;\n readonly artifactDigest: string;\n readonly valueGeneration: number;\n readonly dependencyGeneration: number;\n readonly cookGeneration: number;\n}\n\nexport type MaterialCookIdentityInput = Omit<MaterialCookIdentity, 'cookIdentity'>;\n\nexport interface MaterialCookReceipt {\n readonly schemaVersion: 'material-cook/3';\n readonly sourceClosure: readonly string[];\n readonly profile: string;\n readonly compilerVersion: string;\n readonly identity: MaterialCookIdentity;\n readonly derivedInterface: { readonly layoutIdentity: string };\n}\n\nexport interface MaterialParameterContract {\n readonly parameters: readonly MaterialParameter[];\n readonly values: Readonly<Record<string, MaterialValue | null>>;\n}\n\nexport interface CookedMaterialRecord {\n readonly schemaVersion: 'material-cook/3';\n readonly guid: string;\n readonly authored?: MaterialAsset;\n readonly materialGuid?: string;\n readonly publicationGeneration?: number;\n readonly specializationKey?: string;\n readonly artifactDigest?: string;\n readonly sourceClosure?: readonly string[];\n readonly parameterContract?: MaterialParameterContract;\n readonly resolved: {\n readonly passes: readonly MaterialPass[];\n readonly parameters: readonly MaterialParameter[];\n readonly values: Readonly<Record<string, MaterialValue | null>>;\n };\n readonly refs: MaterialCookRefs;\n readonly artifact: MaterialCookArtifact;\n readonly receipt: MaterialCookReceipt;\n}\n\nexport interface MaterialCookRecordError {\n readonly code: 'material-cook-record-invalid';\n readonly expected: string;\n readonly hint: string;\n readonly detail: {\n readonly field: string;\n readonly actual?: unknown;\n readonly action: string;\n };\n}\n\nexport interface MaterialCookIdentityExpectation {\n readonly layoutIdentity?: string;\n readonly artifactDigest?: string;\n readonly inputDigest?: string;\n}\n\nfunction unique(values: readonly string[]): readonly string[] {\n return [...new Set(values)].sort();\n}\n\nfunction guidText(value: string | Uint8Array): string {\n return typeof value === 'string'\n ? value\n : Array.from(value, (byte) => byte.toString(16).padStart(2, '0')).join('');\n}\n\nfunction cookGuidText(value: MaterialTextureReference): string | undefined {\n return typeof value === 'number' ? undefined : guidText(value);\n}\n\nfunction textureValues(\n values: Readonly<Record<string, MaterialValue | null>> | undefined,\n textureFields: ReadonlySet<string>,\n): readonly MaterialTextureValue[] {\n return Object.entries(values ?? {}).flatMap(([name, value]) => {\n if (value === null) return [];\n if (typeof value === 'string') {\n return textureFields.has(name) ? [{ texture: value }] : [];\n }\n return value !== null &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n 'texture' in value\n ? [value as MaterialTextureValue]\n : [];\n });\n}\n\nexport function collectMaterialCookRefs(material: Partial<MaterialAsset>): MaterialCookRefs {\n const textureFields =\n material.parameters === undefined\n ? new Set<string>(MATERIAL_TEXTURE_SLOTS)\n : new Set(\n material.parameters\n .filter((parameter) => parameter.type === 'texture')\n .map((parameter) => parameter.name),\n );\n const textures = textureValues(material.values, textureFields);\n return {\n parent: material.parent ? [guidText(material.parent)] : [],\n textures: unique(\n textures.flatMap((value) => {\n const guid = cookGuidText(value.texture);\n return guid === undefined ? [] : [guid];\n }),\n ),\n samplers: unique(\n textures.flatMap((value) => {\n if (value.sampler === undefined) return [];\n const guid = cookGuidText(value.sampler);\n return guid === undefined ? [] : [guid];\n }),\n ),\n modules: unique((material.passes ?? []).map((pass) => pass.program.module)),\n };\n}\n\nexport function createMaterialArtifactDigest(bytes: Uint8Array): string {\n return `sha256:${bytesToHex(sha256(bytes))}`;\n}\n\nfunction jsonValue(value: unknown): unknown {\n if (value instanceof Uint8Array) return [...value];\n if (Array.isArray(value)) return value.map(jsonValue);\n if (value !== null && typeof value === 'object') {\n return Object.fromEntries(\n Object.entries(value)\n .filter(([, entry]) => entry !== undefined)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([key, entry]) => [key, jsonValue(entry)]),\n );\n }\n return value;\n}\n\nexport function createMaterialCookIdentity(input: MaterialCookIdentityInput): MaterialCookIdentity {\n const cookIdentity = createMaterialArtifactDigest(\n new TextEncoder().encode(\n JSON.stringify(\n jsonValue({\n materialContractDigest: input.materialContractDigest,\n sourceRevision: input.sourceRevision,\n sourceClosureDigest: input.sourceClosureDigest,\n layoutIdentity: input.layoutIdentity,\n programIdentity: input.programIdentity,\n pipelineIdentity: input.pipelineIdentity,\n compilerFingerprint: input.compilerFingerprint,\n wasm: input.wasm,\n artifactDigest: input.artifactDigest,\n }),\n ),\n ),\n );\n return { ...input, cookIdentity };\n}\n\nexport function serializeCookedMaterialRecord(record: CookedMaterialRecord): string {\n return JSON.stringify(jsonValue(record));\n}\n\nexport function serializeMaterialCookReceipt(receipt: MaterialCookReceipt): string {\n return JSON.stringify(jsonValue({ ...receipt, sourceClosure: unique(receipt.sourceClosure) }));\n}\n\nfunction invalid(field: string, actual?: unknown): Result<never, MaterialCookRecordError> {\n return err({\n code: 'material-cook-record-invalid',\n expected: 'a complete material-cook/3 record with layered identity and provenance',\n hint: 're-cook the material and publish its record, artifact, references, and receipt together',\n detail: {\n field,\n ...(actual === undefined ? {} : { actual }),\n action: 'inspect the named field and recook the material generation',\n },\n });\n}\n\nconst IDENTITY_FIELDS = [\n 'materialContractDigest',\n 'sourceRevision',\n 'sourceClosureDigest',\n 'layoutIdentity',\n 'programIdentity',\n 'pipelineIdentity',\n 'materialPublicationIdentity',\n 'cookIdentity',\n 'compilerFingerprint',\n 'artifactDigest',\n] as const;\n\nfunction isGeneration(value: unknown): value is number {\n return typeof value === 'number' && Number.isSafeInteger(value) && value >= 1;\n}\n\nfunction validateIdentity(value: unknown): Result<MaterialCookIdentity, MaterialCookRecordError> {\n if (value === null || typeof value !== 'object') return invalid('receipt.identity', value);\n const candidate = value as Record<string, unknown>;\n for (const field of IDENTITY_FIELDS) {\n if (typeof candidate[field] !== 'string' || candidate[field].length === 0) {\n return invalid(`receipt.identity.${field}`, candidate[field]);\n }\n }\n if (candidate.wasm === null || typeof candidate.wasm !== 'object') {\n return invalid('receipt.identity.wasm', candidate.wasm);\n }\n const wasm = candidate.wasm as Record<string, unknown>;\n for (const field of ['sourceContentKey', 'artifactSha256', 'glueSha256']) {\n if (typeof wasm[field] !== 'string' || wasm[field].length === 0) {\n return invalid(`receipt.identity.wasm.${field}`, wasm[field]);\n }\n }\n for (const field of ['valueGeneration', 'dependencyGeneration', 'cookGeneration']) {\n if (!isGeneration(candidate[field]))\n return invalid(`receipt.identity.${field}`, candidate[field]);\n }\n return ok({\n ...candidate,\n wasm: wasm as unknown as MaterialCookWasmProvenance,\n } as MaterialCookIdentity);\n}\n\nexport function validateMaterialCookReceipt(\n value: unknown,\n expected: MaterialCookIdentityExpectation = {},\n): Result<MaterialCookReceipt, MaterialCookRecordError> {\n if (value === null || typeof value !== 'object') return invalid('receipt');\n const candidate = value as Record<string, unknown>;\n if (candidate.schemaVersion !== 'material-cook/3')\n return invalid('receipt.schemaVersion', candidate.schemaVersion);\n const identityResult = validateIdentity(candidate.identity);\n if (!identityResult.ok) return identityResult;\n const identity = identityResult.value;\n if (candidate.derivedInterface === null || typeof candidate.derivedInterface !== 'object') {\n return invalid('receipt.derivedInterface', candidate.derivedInterface);\n }\n const derivedInterface = candidate.derivedInterface as Record<string, unknown>;\n if (derivedInterface.layoutIdentity !== identity.layoutIdentity) {\n return invalid('receipt.derivedInterface.layoutIdentity', derivedInterface.layoutIdentity);\n }\n for (const field of ['sourceClosure', 'profile', 'compilerVersion']) {\n const fieldValue = candidate[field];\n if (\n (field === 'sourceClosure' && !Array.isArray(fieldValue)) ||\n (field !== 'sourceClosure' && typeof fieldValue !== 'string')\n ) {\n return invalid(`receipt.${field}`, fieldValue);\n }\n }\n const sourceClosure = candidate.sourceClosure;\n if (Array.isArray(sourceClosure) && sourceClosure.some((path) => typeof path !== 'string')) {\n return invalid('receipt.sourceClosure', sourceClosure);\n }\n if (\n expected.layoutIdentity !== undefined &&\n identity.layoutIdentity !== expected.layoutIdentity\n ) {\n return invalid('receipt.identity.layoutIdentity', identity.layoutIdentity);\n }\n if (\n expected.artifactDigest !== undefined &&\n identity.artifactDigest !== expected.artifactDigest\n ) {\n return invalid('receipt.identity.artifactDigest', identity.artifactDigest);\n }\n if (expected.inputDigest !== undefined && identity.cookIdentity !== expected.inputDigest) {\n return invalid('receipt.identity.cookIdentity', identity.cookIdentity);\n }\n return ok({\n schemaVersion: 'material-cook/3',\n sourceClosure: candidate.sourceClosure as string[],\n profile: candidate.profile as string,\n compilerVersion: candidate.compilerVersion as string,\n identity,\n derivedInterface: { layoutIdentity: derivedInterface.layoutIdentity as string },\n });\n}\n\nexport function validateCookedMaterialRecord(\n value: unknown,\n): Result<CookedMaterialRecord, MaterialCookRecordError> {\n if (value === null || typeof value !== 'object') return invalid('record');\n const candidate = value as Record<string, unknown>;\n if (candidate.schemaVersion !== 'material-cook/3')\n return invalid('schemaVersion', candidate.schemaVersion);\n if (typeof candidate.guid !== 'string' || !candidate.guid) return invalid('guid');\n if (candidate.materialGuid !== undefined && typeof candidate.materialGuid !== 'string')\n return invalid('materialGuid');\n if (\n candidate.publicationGeneration !== undefined &&\n !isGeneration(candidate.publicationGeneration)\n )\n return invalid('publicationGeneration', candidate.publicationGeneration);\n if (candidate.specializationKey !== undefined && typeof candidate.specializationKey !== 'string')\n return invalid('specializationKey');\n if (candidate.artifactDigest !== undefined && typeof candidate.artifactDigest !== 'string')\n return invalid('artifactDigest');\n if (\n candidate.sourceClosure !== undefined &&\n (!Array.isArray(candidate.sourceClosure) ||\n candidate.sourceClosure.some((path) => typeof path !== 'string'))\n )\n return invalid('sourceClosure');\n if (candidate.parameterContract !== undefined) {\n if (candidate.parameterContract === null || typeof candidate.parameterContract !== 'object')\n return invalid('parameterContract');\n const parameterContract = candidate.parameterContract as Record<string, unknown>;\n if (!Array.isArray(parameterContract.parameters))\n return invalid('parameterContract.parameters');\n if (\n parameterContract.values === null ||\n typeof parameterContract.values !== 'object' ||\n Array.isArray(parameterContract.values)\n )\n return invalid('parameterContract.values');\n }\n if (candidate.resolved === null || typeof candidate.resolved !== 'object')\n return invalid('resolved');\n if (candidate.refs === null || typeof candidate.refs !== 'object') return invalid('refs');\n if (candidate.artifact === null || typeof candidate.artifact !== 'object')\n return invalid('artifact');\n if (candidate.receipt === null || typeof candidate.receipt !== 'object')\n return invalid('receipt');\n const artifact = candidate.artifact as Record<string, unknown>;\n if (\n typeof artifact.digest !== 'string' ||\n (!Array.isArray(artifact.bytes) && !ArrayBuffer.isView(artifact.bytes))\n ) {\n return invalid('artifact');\n }\n const receiptResult = validateMaterialCookReceipt(candidate.receipt, {\n artifactDigest: artifact.digest as string,\n });\n if (!receiptResult.ok) return receiptResult;\n if (candidate.artifactDigest !== undefined && candidate.artifactDigest !== artifact.digest)\n return invalid('artifactDigest', candidate.artifactDigest);\n if (\n candidate.publicationGeneration !== undefined &&\n receiptResult.value.identity.cookGeneration !== candidate.publicationGeneration\n )\n return invalid('receipt.identity.cookGeneration', receiptResult.value.identity.cookGeneration);\n const normalized = {\n ...candidate,\n artifact: {\n ...artifact,\n bytes: ArrayBuffer.isView(artifact.bytes)\n ? Uint8Array.from(artifact.bytes as Uint8Array)\n : Uint8Array.from(artifact.bytes as number[]),\n },\n receipt: receiptResult.value,\n } as CookedMaterialRecord;\n return ok(normalized);\n}\n\nexport function projectCookedMaterialRecord(\n record: CookedMaterialRecord,\n): Omit<CookedMaterialRecord, 'guid' | 'authored'> {\n return {\n resolved: record.resolved,\n refs: record.refs,\n artifact: record.artifact,\n receipt: record.receipt,\n schemaVersion: record.schemaVersion,\n };\n}\n"]}
@@ -0,0 +1,36 @@
1
+ /** Canonical mesh binary wire facts shared by build-time and runtime owners. */
2
+ export declare const MESH_BIN_VERSION: 4;
3
+ export declare const MESH_BIN_PROJECTION_VERSION: 1;
4
+ export declare const MESH_BIN_HEADER_V4_BYTES = 80;
5
+ export declare const MESH_BIN_DIGEST_BYTES = 32;
6
+ export interface MeshBinHeaderV4 {
7
+ readonly version: 4;
8
+ readonly projectionVersion: 1;
9
+ readonly mask: number;
10
+ readonly digest: string;
11
+ readonly stride: number;
12
+ readonly vertexCount: number;
13
+ readonly vertexBytes: number;
14
+ readonly indexCount: number;
15
+ readonly indexWidth: 0 | 2 | 4;
16
+ readonly indexBytes: number;
17
+ readonly jsonBytes: number;
18
+ }
19
+ export interface MeshBinContractError {
20
+ readonly code: 'mesh-bin-header-truncated' | 'mesh-bin-version-unsupported' | 'mesh-bin-header-invalid';
21
+ readonly subject: 'mesh-bin';
22
+ readonly sourceKey: string;
23
+ readonly expected: string;
24
+ readonly actual: string;
25
+ readonly recovery: string;
26
+ }
27
+ export type MeshBinHeaderResult = {
28
+ readonly ok: true;
29
+ readonly value: MeshBinHeaderV4;
30
+ } | {
31
+ readonly ok: false;
32
+ readonly error: MeshBinContractError;
33
+ };
34
+ export declare function writeMeshBinHeader(header: MeshBinHeaderV4, out: Uint8Array): void;
35
+ export declare function decodeMeshBinHeader(bytes: Uint8Array, sourceKey?: string): MeshBinHeaderResult;
36
+ //# sourceMappingURL=mesh-bin-contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mesh-bin-contract.d.ts","sourceRoot":"","sources":["../src/mesh-bin-contract.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAEhF,eAAO,MAAM,gBAAgB,EAAG,CAAU,CAAC;AAC3C,eAAO,MAAM,2BAA2B,EAAG,CAAU,CAAC;AACtD,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAC3C,eAAO,MAAM,qBAAqB,KAAK,CAAC;AAExC,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IACpB,QAAQ,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EACT,2BAA2B,GAC3B,8BAA8B,GAC9B,yBAAyB,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,MAAM,mBAAmB,GAC3B;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAA;CAAE,GACtD;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,oBAAoB,CAAA;CAAE,CAAC;AA+BjE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,EAAE,UAAU,GAAG,IAAI,CAgBjF;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,UAAU,EACjB,SAAS,SAA0B,GAClC,mBAAmB,CA8DrB"}
@@ -0,0 +1,96 @@
1
+ // src/mesh-bin-contract.ts
2
+ var MESH_BIN_VERSION = 4;
3
+ var MESH_BIN_PROJECTION_VERSION = 1;
4
+ var MESH_BIN_HEADER_V4_BYTES = 80;
5
+ var MESH_BIN_DIGEST_BYTES = 32;
6
+ function failure(code, sourceKey, expected, actual) {
7
+ return {
8
+ ok: false,
9
+ error: {
10
+ code,
11
+ subject: "mesh-bin",
12
+ sourceKey,
13
+ expected,
14
+ actual,
15
+ recovery: "re-cook the source with its Meta sidecar through the build-time importer"
16
+ }
17
+ };
18
+ }
19
+ function digestBytes(digest) {
20
+ const bytes = new Uint8Array(MESH_BIN_DIGEST_BYTES);
21
+ bytes.set(new TextEncoder().encode(digest).subarray(0, MESH_BIN_DIGEST_BYTES));
22
+ return bytes;
23
+ }
24
+ function readDigest(bytes) {
25
+ return new TextDecoder().decode(bytes).replace(/\0+$/u, "");
26
+ }
27
+ function writeMeshBinHeader(header, out) {
28
+ if (out.byteLength < MESH_BIN_HEADER_V4_BYTES) {
29
+ throw new RangeError("mesh-bin v4 header output is truncated");
30
+ }
31
+ const view = new DataView(out.buffer, out.byteOffset, out.byteLength);
32
+ view.setUint32(0, header.version, true);
33
+ view.setUint32(4, header.projectionVersion, true);
34
+ view.setUint32(8, header.mask, true);
35
+ view.setUint32(12, header.stride, true);
36
+ view.setUint32(16, header.vertexCount, true);
37
+ view.setUint32(20, header.vertexBytes, true);
38
+ view.setUint32(24, header.indexCount, true);
39
+ view.setUint32(28, header.indexWidth, true);
40
+ view.setUint32(32, header.indexBytes, true);
41
+ view.setUint32(36, header.jsonBytes, true);
42
+ out.set(digestBytes(header.digest), 48);
43
+ }
44
+ function decodeMeshBinHeader(bytes, sourceKey = "<unknown mesh source>") {
45
+ if (bytes.byteLength < MESH_BIN_HEADER_V4_BYTES) {
46
+ return failure(
47
+ "mesh-bin-header-truncated",
48
+ sourceKey,
49
+ `mesh-bin v4 header (${MESH_BIN_HEADER_V4_BYTES} bytes)`,
50
+ `${bytes.byteLength} bytes`
51
+ );
52
+ }
53
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
54
+ const version = view.getUint32(0, true);
55
+ if (version !== MESH_BIN_VERSION) {
56
+ return failure("mesh-bin-version-unsupported", sourceKey, "mesh-bin v4", `version ${version}`);
57
+ }
58
+ const projectionVersion = view.getUint32(4, true);
59
+ const mask = view.getUint32(8, true);
60
+ const stride = view.getUint32(12, true);
61
+ const vertexCount = view.getUint32(16, true);
62
+ const vertexBytes = view.getUint32(20, true);
63
+ const indexCount = view.getUint32(24, true);
64
+ const indexWidth = view.getUint32(28, true);
65
+ const indexBytes = view.getUint32(32, true);
66
+ const jsonBytes = view.getUint32(36, true);
67
+ const digest = readDigest(bytes.subarray(48, 48 + MESH_BIN_DIGEST_BYTES));
68
+ if (projectionVersion !== MESH_BIN_PROJECTION_VERSION || mask === 0 || stride === 0 || !Number.isSafeInteger(vertexCount) || !Number.isSafeInteger(vertexBytes) || !Number.isSafeInteger(indexCount) || !Number.isSafeInteger(indexBytes) || !Number.isSafeInteger(jsonBytes) || indexCount === 0 && indexWidth !== 0 || indexCount > 0 && indexWidth !== 2 && indexWidth !== 4 || indexBytes !== indexCount * indexWidth || vertexBytes !== vertexCount * stride || digest.length === 0) {
69
+ return failure(
70
+ "mesh-bin-header-invalid",
71
+ sourceKey,
72
+ "safe v4 projection, stride, cardinality, and payload byte lengths",
73
+ `projection=${projectionVersion}; mask=${mask}; stride=${stride}; vertexBytes=${vertexBytes}; indexBytes=${indexBytes}; digest=${digest}`
74
+ );
75
+ }
76
+ return {
77
+ ok: true,
78
+ value: {
79
+ version: 4,
80
+ projectionVersion: 1,
81
+ mask,
82
+ digest,
83
+ stride,
84
+ vertexCount,
85
+ vertexBytes,
86
+ indexCount,
87
+ indexWidth,
88
+ indexBytes,
89
+ jsonBytes
90
+ }
91
+ };
92
+ }
93
+
94
+ export { MESH_BIN_DIGEST_BYTES, MESH_BIN_HEADER_V4_BYTES, MESH_BIN_PROJECTION_VERSION, MESH_BIN_VERSION, decodeMeshBinHeader, writeMeshBinHeader };
95
+ //# sourceMappingURL=mesh-bin-contract.mjs.map
96
+ //# sourceMappingURL=mesh-bin-contract.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/mesh-bin-contract.ts"],"names":[],"mappings":"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","file":"mesh-bin-contract.mjs","sourcesContent":["/** Canonical mesh binary wire facts shared by build-time and runtime owners. */\n\nexport const MESH_BIN_VERSION = 4 as const;\nexport const MESH_BIN_PROJECTION_VERSION = 1 as const;\nexport const MESH_BIN_HEADER_V4_BYTES = 80;\nexport const MESH_BIN_DIGEST_BYTES = 32;\n\nexport interface MeshBinHeaderV4 {\n readonly version: 4;\n readonly projectionVersion: 1;\n readonly mask: number;\n readonly digest: string;\n readonly stride: number;\n readonly vertexCount: number;\n readonly vertexBytes: number;\n readonly indexCount: number;\n readonly indexWidth: 0 | 2 | 4;\n readonly indexBytes: number;\n readonly jsonBytes: number;\n}\n\nexport interface MeshBinContractError {\n readonly code:\n | 'mesh-bin-header-truncated'\n | 'mesh-bin-version-unsupported'\n | 'mesh-bin-header-invalid';\n readonly subject: 'mesh-bin';\n readonly sourceKey: string;\n readonly expected: string;\n readonly actual: string;\n readonly recovery: string;\n}\n\nexport type MeshBinHeaderResult =\n | { readonly ok: true; readonly value: MeshBinHeaderV4 }\n | { readonly ok: false; readonly error: MeshBinContractError };\n\nfunction failure(\n code: MeshBinContractError['code'],\n sourceKey: string,\n expected: string,\n actual: string,\n): MeshBinHeaderResult {\n return {\n ok: false,\n error: {\n code,\n subject: 'mesh-bin',\n sourceKey,\n expected,\n actual,\n recovery: 're-cook the source with its Meta sidecar through the build-time importer',\n },\n };\n}\n\nfunction digestBytes(digest: string): Uint8Array {\n const bytes = new Uint8Array(MESH_BIN_DIGEST_BYTES);\n bytes.set(new TextEncoder().encode(digest).subarray(0, MESH_BIN_DIGEST_BYTES));\n return bytes;\n}\n\nfunction readDigest(bytes: Uint8Array): string {\n return new TextDecoder().decode(bytes).replace(/\\0+$/u, '');\n}\n\nexport function writeMeshBinHeader(header: MeshBinHeaderV4, out: Uint8Array): void {\n if (out.byteLength < MESH_BIN_HEADER_V4_BYTES) {\n throw new RangeError('mesh-bin v4 header output is truncated');\n }\n const view = new DataView(out.buffer, out.byteOffset, out.byteLength);\n view.setUint32(0, header.version, true);\n view.setUint32(4, header.projectionVersion, true);\n view.setUint32(8, header.mask, true);\n view.setUint32(12, header.stride, true);\n view.setUint32(16, header.vertexCount, true);\n view.setUint32(20, header.vertexBytes, true);\n view.setUint32(24, header.indexCount, true);\n view.setUint32(28, header.indexWidth, true);\n view.setUint32(32, header.indexBytes, true);\n view.setUint32(36, header.jsonBytes, true);\n out.set(digestBytes(header.digest), 48);\n}\n\nexport function decodeMeshBinHeader(\n bytes: Uint8Array,\n sourceKey = '<unknown mesh source>',\n): MeshBinHeaderResult {\n if (bytes.byteLength < MESH_BIN_HEADER_V4_BYTES) {\n return failure(\n 'mesh-bin-header-truncated',\n sourceKey,\n `mesh-bin v4 header (${MESH_BIN_HEADER_V4_BYTES} bytes)`,\n `${bytes.byteLength} bytes`,\n );\n }\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n const version = view.getUint32(0, true);\n if (version !== MESH_BIN_VERSION) {\n return failure('mesh-bin-version-unsupported', sourceKey, 'mesh-bin v4', `version ${version}`);\n }\n const projectionVersion = view.getUint32(4, true);\n const mask = view.getUint32(8, true);\n const stride = view.getUint32(12, true);\n const vertexCount = view.getUint32(16, true);\n const vertexBytes = view.getUint32(20, true);\n const indexCount = view.getUint32(24, true);\n const indexWidth = view.getUint32(28, true);\n const indexBytes = view.getUint32(32, true);\n const jsonBytes = view.getUint32(36, true);\n const digest = readDigest(bytes.subarray(48, 48 + MESH_BIN_DIGEST_BYTES));\n if (\n projectionVersion !== MESH_BIN_PROJECTION_VERSION ||\n mask === 0 ||\n stride === 0 ||\n !Number.isSafeInteger(vertexCount) ||\n !Number.isSafeInteger(vertexBytes) ||\n !Number.isSafeInteger(indexCount) ||\n !Number.isSafeInteger(indexBytes) ||\n !Number.isSafeInteger(jsonBytes) ||\n (indexCount === 0 && indexWidth !== 0) ||\n (indexCount > 0 && indexWidth !== 2 && indexWidth !== 4) ||\n indexBytes !== indexCount * indexWidth ||\n vertexBytes !== vertexCount * stride ||\n digest.length === 0\n ) {\n return failure(\n 'mesh-bin-header-invalid',\n sourceKey,\n 'safe v4 projection, stride, cardinality, and payload byte lengths',\n `projection=${projectionVersion}; mask=${mask}; stride=${stride}; vertexBytes=${vertexBytes}; indexBytes=${indexBytes}; digest=${digest}`,\n );\n }\n return {\n ok: true,\n value: {\n version: 4,\n projectionVersion: 1,\n mask,\n digest,\n stride,\n vertexCount,\n vertexBytes,\n indexCount,\n indexWidth: indexWidth as 0 | 2 | 4,\n indexBytes,\n jsonBytes,\n },\n };\n}\n"]}
package/dist/name.mjs ADDED
@@ -0,0 +1,22 @@
1
+ // src/deriveAssetName.ts
2
+ function baseName(p) {
3
+ const trimmed = p.replace(/[/\\]+$/, "");
4
+ const idx = Math.max(trimmed.lastIndexOf("/"), trimmed.lastIndexOf("\\"));
5
+ return idx === -1 ? trimmed : trimmed.slice(idx + 1);
6
+ }
7
+ function deriveAssetName(packagePath, assetCount, storedName) {
8
+ if (packagePath === null) {
9
+ return storedName ?? "";
10
+ }
11
+ if (assetCount === 1) {
12
+ return baseName(packagePath);
13
+ }
14
+ if (storedName !== void 0) {
15
+ return storedName;
16
+ }
17
+ return baseName(packagePath);
18
+ }
19
+
20
+ export { deriveAssetName };
21
+ //# sourceMappingURL=name.mjs.map
22
+ //# sourceMappingURL=name.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/deriveAssetName.ts"],"names":[],"mappings":";AAOA,SAAS,SAAS,CAAA,EAAmB;AACnC,EAAA,MAAM,OAAA,GAAU,CAAA,CAAE,OAAA,CAAQ,SAAA,EAAW,EAAE,CAAA;AACvC,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,OAAA,CAAQ,WAAA,CAAY,GAAG,CAAA,EAAG,OAAA,CAAQ,WAAA,CAAY,IAAI,CAAC,CAAA;AACxE,EAAA,OAAO,QAAQ,EAAA,GAAK,OAAA,GAAU,OAAA,CAAQ,KAAA,CAAM,MAAM,CAAC,CAAA;AACrD;AAeO,SAAS,eAAA,CACd,WAAA,EACA,UAAA,EACA,UAAA,EACQ;AACR,EAAA,IAAI,gBAAgB,IAAA,EAAM;AACxB,IAAA,OAAO,UAAA,IAAc,EAAA;AAAA,EACvB;AACA,EAAA,IAAI,eAAe,CAAA,EAAG;AACpB,IAAA,OAAO,SAAS,WAAW,CAAA;AAAA,EAC7B;AACA,EAAA,IAAI,eAAe,MAAA,EAAW;AAC5B,IAAA,OAAO,UAAA;AAAA,EACT;AACA,EAAA,OAAO,SAAS,WAAW,CAAA;AAC7B","file":"name.mjs","sourcesContent":["/**\n * Last path segment of a `/`- or `\\`-separated path, trailing separators\n * stripped. Inlined rather than imported from `node:path` so this module stays\n * browser-safe: the dev-server pack path (`vite-plugin-pack` `/__pack/`) runs\n * `buildCatalog` -> `deriveAssetName` in client code where `node:path` is\n * externalized and `path.basename` throws.\n */\nfunction baseName(p: string): string {\n const trimmed = p.replace(/[/\\\\]+$/, '');\n const idx = Math.max(trimmed.lastIndexOf('/'), trimmed.lastIndexOf('\\\\'));\n return idx === -1 ? trimmed : trimmed.slice(idx + 1);\n}\n\n/**\n * Derive an asset's display name from package metadata.\n *\n * Pure function -- zero IO, zero side effects, browser-safe. Build-time\n * (build-catalog) and runtime (resolveName) share this single source of truth\n * for the XOR name-resolution rules (plan-strategy D-6).\n *\n * Branches:\n * 1. single-asset package (assetCount === 1) -> baseName(packagePath)\n * 2. multi-asset package + storedName -> storedName\n * 3. multi-asset package + no storedName (AC-15.1) -> baseName(packagePath)\n * 4. null packagePath + no storedName (AC-15.2) -> ''\n */\nexport function deriveAssetName(\n packagePath: string | null,\n assetCount: number,\n storedName?: string,\n): string {\n if (packagePath === null) {\n return storedName ?? '';\n }\n if (assetCount === 1) {\n return baseName(packagePath);\n }\n if (storedName !== undefined) {\n return storedName;\n }\n return baseName(packagePath);\n}\n"]}
@@ -0,0 +1,47 @@
1
+ import type { AssetCodec, AssetStageError, CookProduct, Result } from '@forgeax/engine-types';
2
+ export interface NativeCookArtifact {
3
+ readonly mediaType: string;
4
+ readonly assetCodec?: AssetCodec;
5
+ readonly bytes: Uint8Array;
6
+ }
7
+ export interface NativeCookDraft<P = unknown> {
8
+ readonly guid: string;
9
+ readonly payload: P;
10
+ readonly refs: readonly string[];
11
+ readonly artifacts: Readonly<Record<string, NativeCookArtifact>>;
12
+ readonly inputFingerprint: string;
13
+ }
14
+ export interface NativeCooker<P = unknown, I = unknown> {
15
+ readonly key: string;
16
+ readonly discover?: (input: unknown) => I | Promise<I>;
17
+ cook(input: I): NativeCookDraft<P> | Promise<NativeCookDraft<P>>;
18
+ }
19
+ export interface NativeCookTransactionSnapshot<P = unknown> {
20
+ readonly draft: NativeCookDraft<P>;
21
+ readonly generation: number;
22
+ }
23
+ export interface NativeCookTransactionOptions<P = unknown, I = unknown> {
24
+ readonly key: string;
25
+ readonly input: I;
26
+ readonly previous?: NativeCookTransactionSnapshot<P>;
27
+ readonly validate?: (draft: NativeCookDraft<P>) => string | undefined;
28
+ readonly publish?: (draft: NativeCookDraft<P>, generation: number) => void | Promise<void>;
29
+ }
30
+ export interface NativeCookTransactionResult<P = unknown> extends NativeCookTransactionSnapshot<P> {
31
+ readonly status: 'committed' | 'recovered';
32
+ readonly lastKnownGood: NativeCookDraft<P>;
33
+ readonly candidateGeneration: number;
34
+ readonly lastKnownGoodGeneration: number;
35
+ readonly recoveryHint?: string;
36
+ }
37
+ /** Injectable build-time table for native authored Pack producers. */
38
+ export declare class NativeCookerRegistry {
39
+ private readonly cookers;
40
+ register(cooker: NativeCooker): void;
41
+ get(key: string): NativeCooker | undefined;
42
+ registeredCookers(): readonly string[];
43
+ runDraft<P = unknown, I = unknown>(key: string, input: I): Promise<Result<NativeCookDraft<P>, AssetStageError>>;
44
+ run<P = unknown, I = unknown>(key: string, input: I): Promise<Result<CookProduct<P>, AssetStageError>>;
45
+ runTransaction<P = unknown, I = unknown>(options: NativeCookTransactionOptions<P, I>): Promise<Result<NativeCookTransactionResult<P>, AssetStageError>>;
46
+ }
47
+ //# sourceMappingURL=native-cooker-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-cooker-registry.d.ts","sourceRoot":"","sources":["../src/native-cooker-registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ /** Node/build-time native cooker registry. The browser-safe pack root excludes this seam. */
2
+ export * from './native-cooker-registry.js';
3
+ //# sourceMappingURL=native-cooker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-cooker.d.ts","sourceRoot":"","sources":["../src/native-cooker.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,cAAc,6BAA6B,CAAC"}