@forgeax/engine-pack 0.1.2

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 (228) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +370 -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__/pack-v2-fixture-migration.test.d.ts +2 -0
  51. package/dist/__tests__/pack-v2-fixture-migration.test.d.ts.map +1 -0
  52. package/dist/__tests__/pack-v2-schema.test.d.ts +2 -0
  53. package/dist/__tests__/pack-v2-schema.test.d.ts.map +1 -0
  54. package/dist/__tests__/pack.unit.test.d.ts +2 -0
  55. package/dist/__tests__/pack.unit.test.d.ts.map +1 -0
  56. package/dist/__tests__/producer-contract-schema.unit.test.d.ts +2 -0
  57. package/dist/__tests__/producer-contract-schema.unit.test.d.ts.map +1 -0
  58. package/dist/__tests__/resolve-asset-source.test.d.ts +2 -0
  59. package/dist/__tests__/resolve-asset-source.test.d.ts.map +1 -0
  60. package/dist/__tests__/runtime-projection.unit.test.d.ts +2 -0
  61. package/dist/__tests__/runtime-projection.unit.test.d.ts.map +1 -0
  62. package/dist/__tests__/scanner-inventory.test.d.ts +2 -0
  63. package/dist/__tests__/scanner-inventory.test.d.ts.map +1 -0
  64. package/dist/__tests__/scanner-mount-cycle.test.d.ts +2 -0
  65. package/dist/__tests__/scanner-mount-cycle.test.d.ts.map +1 -0
  66. package/dist/__tests__/scriptable-pack-cli.integration.test.d.ts +2 -0
  67. package/dist/__tests__/scriptable-pack-cli.integration.test.d.ts.map +1 -0
  68. package/dist/__tests__/scriptable-pack-ddc-key.unit.test.d.ts +2 -0
  69. package/dist/__tests__/scriptable-pack-ddc-key.unit.test.d.ts.map +1 -0
  70. package/dist/__tests__/scriptable-pack.test-d.d.ts +2 -0
  71. package/dist/__tests__/scriptable-pack.test-d.d.ts.map +1 -0
  72. package/dist/__tests__/scriptable-pack.unit.test.d.ts +2 -0
  73. package/dist/__tests__/scriptable-pack.unit.test.d.ts.map +1 -0
  74. package/dist/__tests__/topology-actions.unit.test.d.ts +2 -0
  75. package/dist/__tests__/topology-actions.unit.test.d.ts.map +1 -0
  76. package/dist/__tests__/topology.unit.test.d.ts +2 -0
  77. package/dist/__tests__/topology.unit.test.d.ts.map +1 -0
  78. package/dist/artifact-path.d.ts +9 -0
  79. package/dist/artifact-path.d.ts.map +1 -0
  80. package/dist/atlas/run-atlas.d.ts +8 -0
  81. package/dist/atlas/run-atlas.d.ts.map +1 -0
  82. package/dist/atlas/shelf-pack.d.ts +55 -0
  83. package/dist/atlas/shelf-pack.d.ts.map +1 -0
  84. package/dist/bridge.d.ts +2 -0
  85. package/dist/bridge.d.ts.map +1 -0
  86. package/dist/bridge.mjs +3 -0
  87. package/dist/bridge.mjs.map +1 -0
  88. package/dist/builtin.d.ts +24 -0
  89. package/dist/builtin.d.ts.map +1 -0
  90. package/dist/cli-asset.d.ts +22 -0
  91. package/dist/cli-asset.d.ts.map +1 -0
  92. package/dist/cli-asset.mjs +9950 -0
  93. package/dist/cli-asset.mjs.map +1 -0
  94. package/dist/config.d.ts +6 -0
  95. package/dist/config.d.ts.map +1 -0
  96. package/dist/config.mjs +29 -0
  97. package/dist/config.mjs.map +1 -0
  98. package/dist/deriveAssetName.d.ts +15 -0
  99. package/dist/deriveAssetName.d.ts.map +1 -0
  100. package/dist/errors.d.ts +30 -0
  101. package/dist/errors.d.ts.map +1 -0
  102. package/dist/errors.mjs +19 -0
  103. package/dist/errors.mjs.map +1 -0
  104. package/dist/evidence/material-cook.d.ts +70 -0
  105. package/dist/evidence/material-cook.d.ts.map +1 -0
  106. package/dist/evidence/offline-evidence.d.ts +25 -0
  107. package/dist/evidence/offline-evidence.d.ts.map +1 -0
  108. package/dist/evidence/source-inventory.d.ts +29 -0
  109. package/dist/evidence/source-inventory.d.ts.map +1 -0
  110. package/dist/guid.d.ts +45 -0
  111. package/dist/guid.d.ts.map +1 -0
  112. package/dist/guid.mjs +94 -0
  113. package/dist/guid.mjs.map +1 -0
  114. package/dist/index.d.ts +15 -0
  115. package/dist/index.d.ts.map +1 -0
  116. package/dist/index.mjs +8475 -0
  117. package/dist/index.mjs.map +1 -0
  118. package/dist/material/artifact-writer.d.ts +14 -0
  119. package/dist/material/artifact-writer.d.ts.map +1 -0
  120. package/dist/mesh-bin-contract.d.ts +36 -0
  121. package/dist/mesh-bin-contract.d.ts.map +1 -0
  122. package/dist/name.mjs +22 -0
  123. package/dist/name.mjs.map +1 -0
  124. package/dist/native-cooker-registry.d.ts +28 -0
  125. package/dist/native-cooker-registry.d.ts.map +1 -0
  126. package/dist/native-cooker.d.ts +3 -0
  127. package/dist/native-cooker.d.ts.map +1 -0
  128. package/dist/native-cooker.mjs +105 -0
  129. package/dist/native-cooker.mjs.map +1 -0
  130. package/dist/producer-contract.d.ts +19 -0
  131. package/dist/producer-contract.d.ts.map +1 -0
  132. package/dist/resolve-asset-source.d.ts +4 -0
  133. package/dist/resolve-asset-source.d.ts.map +1 -0
  134. package/dist/resolve-asset-source.mjs +99 -0
  135. package/dist/resolve-asset-source.mjs.map +1 -0
  136. package/dist/runtime-projection.d.ts +14 -0
  137. package/dist/runtime-projection.d.ts.map +1 -0
  138. package/dist/scanner.d.ts +80 -0
  139. package/dist/scanner.d.ts.map +1 -0
  140. package/dist/scanner.mjs +9015 -0
  141. package/dist/scanner.mjs.map +1 -0
  142. package/dist/schema-compiled.d.ts +12 -0
  143. package/dist/schema-compiled.d.ts.map +1 -0
  144. package/dist/schema.mjs +7369 -0
  145. package/dist/schema.mjs.map +1 -0
  146. package/dist/scriptable-pack-node.d.ts +67 -0
  147. package/dist/scriptable-pack-node.d.ts.map +1 -0
  148. package/dist/scriptable-pack-node.mjs +1590 -0
  149. package/dist/scriptable-pack-node.mjs.map +1 -0
  150. package/dist/scriptable-pack-worker.d.ts +2 -0
  151. package/dist/scriptable-pack-worker.d.ts.map +1 -0
  152. package/dist/scriptable-pack-worker.mjs +223 -0
  153. package/dist/scriptable-pack-worker.mjs.map +1 -0
  154. package/dist/scriptable-pack.d.ts +525 -0
  155. package/dist/scriptable-pack.d.ts.map +1 -0
  156. package/dist/scriptable-pack.mjs +583 -0
  157. package/dist/scriptable-pack.mjs.map +1 -0
  158. package/dist/topology.d.ts +10 -0
  159. package/dist/topology.d.ts.map +1 -0
  160. package/package.json +129 -0
  161. package/schema/meta.schema.json +173 -0
  162. package/schema/pack.schema.json +232 -0
  163. package/src/__tests__/ai-recovery.unit.test.ts +114 -0
  164. package/src/__tests__/artifact-path.test.ts +41 -0
  165. package/src/__tests__/asset-evidence-error-hints.test.ts +46 -0
  166. package/src/__tests__/asset-evidence-lifecycle.test.ts +104 -0
  167. package/src/__tests__/asset-evidence-schema.test.ts +86 -0
  168. package/src/__tests__/atlas-cli-region-mismatch.test.ts +134 -0
  169. package/src/__tests__/atlas-error-code-owner.test-d.ts +23 -0
  170. package/src/__tests__/cli-asset-evidence.integration.test.ts +172 -0
  171. package/src/__tests__/cli.unit.test.ts +448 -0
  172. package/src/__tests__/evidence-source-inventory.unit.test.ts +37 -0
  173. package/src/__tests__/guid-collision.unit.test.ts +112 -0
  174. package/src/__tests__/guid-validator-surface.unit.test.ts +20 -0
  175. package/src/__tests__/load-asset-config.test.ts +121 -0
  176. package/src/__tests__/material-cook-dependencies.unit.test.ts +45 -0
  177. package/src/__tests__/material-cook-receipt.unit.test.ts +91 -0
  178. package/src/__tests__/material-cook-schema.unit.test.ts +98 -0
  179. package/src/__tests__/mesh-bin-consumer-surface.unit.test.ts +21 -0
  180. package/src/__tests__/mesh-bin-contract.unit.test.ts +32 -0
  181. package/src/__tests__/meta-schema-optional.test.ts +116 -0
  182. package/src/__tests__/meta-source-overrides.unit.test.ts +71 -0
  183. package/src/__tests__/native-cooker-registry.test.ts +64 -0
  184. package/src/__tests__/offline-evidence-artifact-verification-owner.test-d.ts +64 -0
  185. package/src/__tests__/offline-evidence.integration.test.ts +106 -0
  186. package/src/__tests__/pack-v2-fixture-migration.test.ts +64 -0
  187. package/src/__tests__/pack-v2-schema.test.ts +142 -0
  188. package/src/__tests__/pack.unit.test.ts +2218 -0
  189. package/src/__tests__/producer-contract-schema.unit.test.ts +92 -0
  190. package/src/__tests__/resolve-asset-source.test.ts +121 -0
  191. package/src/__tests__/runtime-projection.unit.test.ts +87 -0
  192. package/src/__tests__/scanner-inventory.test.ts +72 -0
  193. package/src/__tests__/scanner-mount-cycle.test.ts +232 -0
  194. package/src/__tests__/scriptable-pack-cli.integration.test.ts +47 -0
  195. package/src/__tests__/scriptable-pack-ddc-key.unit.test.ts +63 -0
  196. package/src/__tests__/scriptable-pack.test-d.ts +131 -0
  197. package/src/__tests__/scriptable-pack.unit.test.ts +747 -0
  198. package/src/__tests__/topology-actions.unit.test.ts +94 -0
  199. package/src/__tests__/topology.unit.test.ts +85 -0
  200. package/src/artifact-path.ts +69 -0
  201. package/src/atlas/run-atlas.ts +358 -0
  202. package/src/atlas/shelf-pack.ts +176 -0
  203. package/src/atlas/upng-ambient.d.ts +13 -0
  204. package/src/bridge.ts +2 -0
  205. package/src/builtin.ts +79 -0
  206. package/src/cli-asset.ts +590 -0
  207. package/src/config.ts +36 -0
  208. package/src/deriveAssetName.ts +42 -0
  209. package/src/errors.ts +47 -0
  210. package/src/evidence/material-cook.ts +332 -0
  211. package/src/evidence/offline-evidence.ts +90 -0
  212. package/src/evidence/source-inventory.ts +193 -0
  213. package/src/guid.ts +99 -0
  214. package/src/index.ts +104 -0
  215. package/src/material/artifact-writer.ts +26 -0
  216. package/src/mesh-bin-contract.ts +150 -0
  217. package/src/native-cooker-registry.ts +163 -0
  218. package/src/native-cooker.ts +2 -0
  219. package/src/producer-contract.ts +277 -0
  220. package/src/resolve-asset-source.ts +93 -0
  221. package/src/runtime-projection.ts +100 -0
  222. package/src/scanner.ts +716 -0
  223. package/src/schema/material-cook.schema.json +79 -0
  224. package/src/schema-compiled.ts +238 -0
  225. package/src/scriptable-pack-node.ts +1390 -0
  226. package/src/scriptable-pack-worker.ts +306 -0
  227. package/src/scriptable-pack.ts +884 -0
  228. package/src/topology.ts +156 -0
@@ -0,0 +1,583 @@
1
+ import { err, ok } from '@forgeax/engine-types';
2
+ import { uuidv7obj } from 'uuidv7';
3
+
4
+ // src/scriptable-pack.ts
5
+
6
+ // src/errors.ts
7
+ var PackError = class extends Error {
8
+ code;
9
+ expected;
10
+ hint;
11
+ detail;
12
+ constructor(args) {
13
+ super(`[PackError ${args.code}] expected: ${args.expected}; hint: ${args.hint}`);
14
+ this.name = "PackError";
15
+ this.code = args.code;
16
+ this.expected = args.expected;
17
+ this.hint = args.hint;
18
+ this.detail = args.detail;
19
+ }
20
+ };
21
+
22
+ // src/guid.ts
23
+ function brand(bytes) {
24
+ return bytes;
25
+ }
26
+ var HEX_BYTE = Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"));
27
+ function bytesToDashForm(bytes) {
28
+ const h = HEX_BYTE;
29
+ return `${h[bytes[0]]}${h[bytes[1]]}${h[bytes[2]]}${h[bytes[3]]}-${h[bytes[4]]}${h[bytes[5]]}-${h[bytes[6]]}${h[bytes[7]]}-${h[bytes[8]]}${h[bytes[9]]}-${h[bytes[10]]}${h[bytes[11]]}${h[bytes[12]]}${h[bytes[13]]}${h[bytes[14]]}${h[bytes[15]]}`;
30
+ }
31
+ var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
32
+ function isValidAssetGuidString(value) {
33
+ return typeof value === "string" && UUID_RE.test(value);
34
+ }
35
+ function dashFormToBytes(dashForm) {
36
+ const hex = dashForm.replace(/-/g, "");
37
+ const bytes = new Uint8Array(16);
38
+ for (let i = 0; i < 16; i++) {
39
+ bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
40
+ }
41
+ return bytes;
42
+ }
43
+ var AssetGuid = {
44
+ /**
45
+ * Parse a 36-char RFC 4122 dash-form UUID string into an AssetGuid.
46
+ * Returns Ok(AssetGuid) on success or Err(PackError) with code 'pack-guid-malformed' on failure.
47
+ * Never throws for expected failures (requirements §4.2 / §14 / charter proposition 4).
48
+ */
49
+ parse(dashForm) {
50
+ if (!isValidAssetGuidString(dashForm)) {
51
+ return {
52
+ ok: false,
53
+ error: new PackError({
54
+ code: "pack-guid-malformed",
55
+ expected: "36-char RFC 4122 dash-form UUID",
56
+ hint: "use AssetGuid.random() or a UUIDv7 generator; all GUID fields must be 36-char RFC 4122 dash-form",
57
+ detail: {
58
+ raw: dashForm,
59
+ reason: "expected 36-char RFC 4122 dash-form UUID"
60
+ }
61
+ })
62
+ };
63
+ }
64
+ return { ok: true, value: brand(dashFormToBytes(dashForm)) };
65
+ },
66
+ /**
67
+ * Format an AssetGuid as a 36-char RFC 4122 lowercase dash-form string.
68
+ */
69
+ format(guid) {
70
+ return bytesToDashForm(guid);
71
+ },
72
+ /**
73
+ * Test byte-by-byte equality between two AssetGuids.
74
+ */
75
+ equals(a, b) {
76
+ for (let i = 0; i < 16; i++) {
77
+ if (a[i] !== b[i]) return false;
78
+ }
79
+ return true;
80
+ },
81
+ /**
82
+ * Mint a new time-ordered UUIDv7 as an AssetGuid.
83
+ * Works in both Node.js and browser environments.
84
+ */
85
+ random() {
86
+ const uuid = uuidv7obj();
87
+ const bytes = new Uint8Array(16);
88
+ bytes.set(uuid.bytes);
89
+ return brand(bytes);
90
+ }
91
+ };
92
+
93
+ // src/scriptable-pack.ts
94
+ var SCRIPTABLE_PACK_ASSET_KINDS = [
95
+ "mesh",
96
+ "material",
97
+ "scene",
98
+ "texture",
99
+ "equirect",
100
+ "sampler",
101
+ "font",
102
+ "render-pipeline",
103
+ "tileset",
104
+ "video",
105
+ "skeleton",
106
+ "skin",
107
+ "animation-clip",
108
+ "animation-graph",
109
+ "audio",
110
+ "particle-effect"
111
+ ];
112
+ function isScriptablePackAssetKind(value) {
113
+ return SCRIPTABLE_PACK_ASSET_KINDS.includes(value);
114
+ }
115
+ function createScriptablePackAuthoringGateway(port, allocateGuid = AssetGuid.random) {
116
+ const requests = /* @__PURE__ */ new Map();
117
+ async function mutationResult(result) {
118
+ if (!result.ok) return result;
119
+ const inspected = await port.inspect(result.value.sourcePath);
120
+ if (!inspected.ok) return inspected;
121
+ return ok({
122
+ sourcePath: result.value.sourcePath,
123
+ revision: inspected.value.revision,
124
+ meta: inspected.value.meta
125
+ });
126
+ }
127
+ async function dispatch(operation) {
128
+ switch (operation.kind) {
129
+ case "preflight": {
130
+ const preflight = await port.preflight(operation.sourcePath);
131
+ return preflight.ok ? ok({ sourcePath: operation.sourcePath, ...preflight.value }) : preflight;
132
+ }
133
+ case "inspect-meta": {
134
+ const inspected = await port.inspect(operation.sourcePath);
135
+ return inspected.ok ? ok({ sourcePath: operation.sourcePath, ...inspected.value }) : inspected;
136
+ }
137
+ case "rebuild":
138
+ case "cold-cook": {
139
+ const preflight = await port.preflight(operation.sourcePath);
140
+ if (!preflight.ok) return preflight;
141
+ if (operation.expectedRevision !== void 0 && operation.expectedRevision !== preflight.value.revision) {
142
+ return err({
143
+ code: "pack-source-revision-conflict",
144
+ expected: operation.expectedRevision,
145
+ actual: preflight.value.revision,
146
+ hint: "inspect the current source revision, then retry the build with a new requestId",
147
+ retryable: true,
148
+ recoveryActions: ["asset.preflight", "mint-request-id"],
149
+ detail: { requestId: operation.requestId, sourcePath: operation.sourcePath }
150
+ });
151
+ }
152
+ const rebuilt = await port.rebuild(operation.sourcePath, operation.kind);
153
+ return rebuilt.ok ? ok({ sourcePath: operation.sourcePath, ...rebuilt.value }) : rebuilt;
154
+ }
155
+ case "create-scriptable-pack":
156
+ return mutationResult(
157
+ await port.mutate({
158
+ ...operation,
159
+ packageId: allocateGuid(),
160
+ initialOutput: { ...operation.initialOutput, guid: allocateGuid() }
161
+ })
162
+ );
163
+ case "add-output":
164
+ return mutationResult(await port.mutate({ ...operation, guid: allocateGuid() }));
165
+ case "clone-scriptable-pack": {
166
+ const inspected = await port.inspect(operation.sourcePath);
167
+ if (!inspected.ok) return inspected;
168
+ const outputGuids = Object.fromEntries(
169
+ inspected.value.meta.subAssets.map((asset) => [asset.sourceKey, allocateGuid()])
170
+ );
171
+ return mutationResult(
172
+ await port.mutate({
173
+ ...operation,
174
+ packageId: allocateGuid(),
175
+ outputGuids
176
+ })
177
+ );
178
+ }
179
+ case "add-external-asset":
180
+ case "rename-display":
181
+ case "remove-output":
182
+ return mutationResult(await port.mutate(operation));
183
+ }
184
+ }
185
+ return {
186
+ execute(operation) {
187
+ if (operation.requestId.trim().length === 0) {
188
+ return Promise.resolve(
189
+ err({
190
+ code: "pack-source-operation-committed",
191
+ expected: "a non-empty caller-minted requestId",
192
+ actual: operation.requestId,
193
+ hint: "mint a new requestId and retry the operation once",
194
+ retryable: true,
195
+ recoveryActions: ["mint-request-id"],
196
+ detail: { requestId: operation.requestId, sourcePath: operation.sourcePath }
197
+ })
198
+ );
199
+ }
200
+ const fingerprint = JSON.stringify(operation);
201
+ const prior = requests.get(operation.requestId);
202
+ if (prior !== void 0) {
203
+ if (prior.fingerprint === fingerprint) return prior.result;
204
+ return Promise.resolve(
205
+ err({
206
+ code: "pack-source-operation-committed",
207
+ expected: "one immutable operation per requestId",
208
+ actual: operation.kind,
209
+ hint: "read the original operation result or mint a new requestId",
210
+ retryable: false,
211
+ recoveryActions: ["read-operation-run", "mint-request-id"],
212
+ detail: { requestId: operation.requestId, sourcePath: operation.sourcePath }
213
+ })
214
+ );
215
+ }
216
+ const result = dispatch(operation);
217
+ requests.set(operation.requestId, { fingerprint, result });
218
+ return result;
219
+ }
220
+ };
221
+ }
222
+ var SCRIPTABLE_PACK_REQUEST_ID_SCHEMA = {
223
+ type: "string",
224
+ minLength: 1,
225
+ maxLength: 128,
226
+ pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$",
227
+ description: "Caller-minted identity for one idempotent ScriptablePack operation."
228
+ };
229
+ var SCRIPTABLE_PACK_SOURCE_PATH_SCHEMA = {
230
+ type: "string",
231
+ minLength: 8,
232
+ pattern: "^[^/].*\\.pack\\.ts$",
233
+ description: "Game-root-relative ScriptablePack source path."
234
+ };
235
+ var SCRIPTABLE_PACK_OWNER_GUID_SCHEMA = {
236
+ type: "string",
237
+ format: "uuid",
238
+ description: "Catalog GUID used to resolve the producer-owned source subject."
239
+ };
240
+ var SCRIPTABLE_PACK_REVISION_SCHEMA = {
241
+ type: "string",
242
+ minLength: 64,
243
+ maxLength: 64,
244
+ pattern: "^[a-f0-9]{64}$",
245
+ description: "SHA-256 source revision returned by preflight."
246
+ };
247
+ var SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA = { type: "string", minLength: 1 };
248
+ var SCRIPTABLE_PACK_ASSET_KIND_SCHEMA = {
249
+ enum: SCRIPTABLE_PACK_ASSET_KINDS,
250
+ description: "Ordinary Asset kind supported by the ScriptablePack producer/loader matrix."
251
+ };
252
+ var SCRIPTABLE_PACK_NAME_SCHEMA = { type: "string", minLength: 1 };
253
+ function scriptablePackArgsSchema(properties, required, options = {}) {
254
+ const subjectRequired = ["requestId", ...required];
255
+ return {
256
+ type: "object",
257
+ properties: {
258
+ sourcePath: SCRIPTABLE_PACK_SOURCE_PATH_SCHEMA,
259
+ ownerGuid: SCRIPTABLE_PACK_OWNER_GUID_SCHEMA,
260
+ requestId: SCRIPTABLE_PACK_REQUEST_ID_SCHEMA,
261
+ ...properties
262
+ },
263
+ required: subjectRequired,
264
+ ...options.subject === false ? {} : {
265
+ anyOf: [
266
+ { required: [...subjectRequired, "sourcePath"] },
267
+ { required: [...subjectRequired, "ownerGuid"] },
268
+ ...options.guidSubject === false ? [] : [{ required: [...subjectRequired, "guid"] }]
269
+ ]
270
+ },
271
+ additionalProperties: false
272
+ };
273
+ }
274
+ var SOURCE_AUTHORING_OPERATION_DESCRIPTORS = [
275
+ {
276
+ id: "asset-source.create",
277
+ kind: "create",
278
+ domain: "session",
279
+ title: "Create Asset Source",
280
+ argsSchema: scriptablePackArgsSchema(
281
+ {
282
+ name: SCRIPTABLE_PACK_NAME_SCHEMA,
283
+ initialOutput: {
284
+ type: "object",
285
+ properties: {
286
+ sourceKey: SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA,
287
+ kind: SCRIPTABLE_PACK_ASSET_KIND_SCHEMA,
288
+ name: SCRIPTABLE_PACK_NAME_SCHEMA
289
+ },
290
+ required: ["sourceKey", "kind"],
291
+ additionalProperties: false
292
+ }
293
+ },
294
+ ["sourcePath", "initialOutput"],
295
+ { subject: false }
296
+ )
297
+ },
298
+ {
299
+ id: "asset-source.add-output",
300
+ kind: "add-output",
301
+ domain: "session",
302
+ title: "Add Asset Source Output",
303
+ argsSchema: scriptablePackArgsSchema(
304
+ {
305
+ sourceKey: SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA,
306
+ assetKind: SCRIPTABLE_PACK_ASSET_KIND_SCHEMA,
307
+ name: SCRIPTABLE_PACK_NAME_SCHEMA,
308
+ expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA
309
+ },
310
+ ["sourceKey", "assetKind", "expectedRevision"]
311
+ )
312
+ },
313
+ {
314
+ id: "asset-source.add-external-asset",
315
+ kind: "add-external-asset",
316
+ domain: "session",
317
+ title: "Add Asset Source External Asset",
318
+ argsSchema: scriptablePackArgsSchema(
319
+ {
320
+ alias: SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA,
321
+ guid: { type: "string", format: "uuid" },
322
+ expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA
323
+ },
324
+ ["alias", "guid", "expectedRevision"],
325
+ { guidSubject: false }
326
+ )
327
+ },
328
+ {
329
+ id: "asset-source.rename",
330
+ kind: "rename",
331
+ domain: "session",
332
+ title: "Rename Asset Source Display Name",
333
+ argsSchema: scriptablePackArgsSchema(
334
+ {
335
+ target: {
336
+ oneOf: [
337
+ {
338
+ type: "object",
339
+ properties: { kind: { const: "package" } },
340
+ required: ["kind"],
341
+ additionalProperties: false
342
+ },
343
+ {
344
+ type: "object",
345
+ properties: {
346
+ kind: { const: "output" },
347
+ sourceKey: SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA
348
+ },
349
+ required: ["kind", "sourceKey"],
350
+ additionalProperties: false
351
+ }
352
+ ]
353
+ },
354
+ name: SCRIPTABLE_PACK_NAME_SCHEMA,
355
+ expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA
356
+ },
357
+ ["target", "name", "expectedRevision"]
358
+ )
359
+ },
360
+ {
361
+ id: "asset-source.remove-output",
362
+ kind: "remove-output",
363
+ domain: "session",
364
+ title: "Remove Asset Source Output",
365
+ destructive: true,
366
+ argsSchema: scriptablePackArgsSchema(
367
+ {
368
+ sourceKey: SCRIPTABLE_PACK_SOURCE_KEY_SCHEMA,
369
+ confirmIncomingRefs: { type: "array", items: { type: "string" } },
370
+ expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA
371
+ },
372
+ ["sourceKey", "expectedRevision"]
373
+ )
374
+ },
375
+ {
376
+ id: "asset-source.clone",
377
+ kind: "clone",
378
+ domain: "session",
379
+ title: "Clone Asset Source",
380
+ argsSchema: scriptablePackArgsSchema(
381
+ {
382
+ targetPath: SCRIPTABLE_PACK_SOURCE_PATH_SCHEMA,
383
+ expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA
384
+ },
385
+ ["targetPath", "expectedRevision"]
386
+ )
387
+ },
388
+ {
389
+ id: "asset-source.rebuild",
390
+ kind: "rebuild",
391
+ domain: "session",
392
+ title: "Rebuild Asset Source",
393
+ argsSchema: scriptablePackArgsSchema({ expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA }, [
394
+ "expectedRevision"
395
+ ])
396
+ },
397
+ {
398
+ id: "asset-source.cold-cook",
399
+ kind: "cold-cook",
400
+ domain: "session",
401
+ title: "Cold Cook Asset Source",
402
+ argsSchema: scriptablePackArgsSchema({ expectedRevision: SCRIPTABLE_PACK_REVISION_SCHEMA }, [
403
+ "expectedRevision"
404
+ ])
405
+ }
406
+ ];
407
+ function actual(value) {
408
+ if (value === null) return "null";
409
+ if (Array.isArray(value)) return "array";
410
+ if (ArrayBuffer.isView(value)) return value.constructor.name;
411
+ return typeof value;
412
+ }
413
+ function invalid(propertyPath, expected, value, sourcePath) {
414
+ return err({
415
+ code: "pack-source-definition-invalid",
416
+ expected,
417
+ hint: "repair the default exported ScriptablePack definition, then inspect Meta again",
418
+ detail: {
419
+ ...sourcePath === void 0 ? {} : { sourcePath },
420
+ propertyPath,
421
+ actual: actual(value)
422
+ }
423
+ });
424
+ }
425
+ function isRecord(value) {
426
+ return value !== null && typeof value === "object" && !Array.isArray(value);
427
+ }
428
+ function isAssetGuid(value) {
429
+ return value instanceof Uint8Array && value.byteLength === 16;
430
+ }
431
+ function guidKey(guid) {
432
+ return AssetGuid.format(guid);
433
+ }
434
+ function freezeDefinition(definition) {
435
+ const assets = Object.fromEntries(
436
+ Object.entries(definition.assets).map(([sourceKey, descriptor]) => [
437
+ sourceKey,
438
+ Object.freeze({ ...descriptor, guid: descriptor.guid.slice() })
439
+ ])
440
+ );
441
+ const externalAssets = Object.fromEntries(
442
+ Object.entries(definition.externalAssets).map(([alias, guid]) => [
443
+ alias,
444
+ guid.slice()
445
+ ])
446
+ );
447
+ return Object.freeze({
448
+ ...definition,
449
+ packageId: definition.packageId.slice(),
450
+ assets: Object.freeze(assets),
451
+ externalAssets: Object.freeze(externalAssets)
452
+ });
453
+ }
454
+ function validateScriptablePackDefinition(value, sourcePath) {
455
+ if (!isRecord(value))
456
+ return invalid("$", "a ScriptablePack definition object", value, sourcePath);
457
+ if (value.schemaVersion !== "1.0.0") {
458
+ return invalid("$.schemaVersion", "the literal '1.0.0'", value.schemaVersion, sourcePath);
459
+ }
460
+ if (!isAssetGuid(value.packageId)) {
461
+ return invalid("$.packageId", "a 16-byte AssetGuid", value.packageId, sourcePath);
462
+ }
463
+ if (value.name !== void 0 && typeof value.name !== "string") {
464
+ return invalid("$.name", "a string when present", value.name, sourcePath);
465
+ }
466
+ if (!isRecord(value.assets) || Object.keys(value.assets).length === 0) {
467
+ return invalid(
468
+ "$.assets",
469
+ "a non-empty sourceKey to descriptor object",
470
+ value.assets,
471
+ sourcePath
472
+ );
473
+ }
474
+ if (!isRecord(value.externalAssets)) {
475
+ return invalid(
476
+ "$.externalAssets",
477
+ "an alias to AssetGuid object",
478
+ value.externalAssets,
479
+ sourcePath
480
+ );
481
+ }
482
+ if (typeof value.build !== "function") {
483
+ return invalid("$.build", "a build(assetReader) function", value.build, sourcePath);
484
+ }
485
+ const packageGuid = guidKey(value.packageId);
486
+ const localGuids = /* @__PURE__ */ new Set();
487
+ for (const [sourceKey, descriptor] of Object.entries(value.assets)) {
488
+ if (sourceKey.trim().length === 0) {
489
+ return invalid("$.assets", "non-empty sourceKey object keys", sourceKey, sourcePath);
490
+ }
491
+ if (!isRecord(descriptor)) {
492
+ return invalid(
493
+ `$.assets[${JSON.stringify(sourceKey)}]`,
494
+ "an asset descriptor",
495
+ descriptor,
496
+ sourcePath
497
+ );
498
+ }
499
+ if (!isAssetGuid(descriptor.guid)) {
500
+ return invalid(
501
+ `$.assets[${JSON.stringify(sourceKey)}].guid`,
502
+ "a 16-byte AssetGuid",
503
+ descriptor.guid,
504
+ sourcePath
505
+ );
506
+ }
507
+ if (typeof descriptor.kind !== "string" || !isScriptablePackAssetKind(descriptor.kind)) {
508
+ return invalid(
509
+ `$.assets[${JSON.stringify(sourceKey)}].kind`,
510
+ "one of SCRIPTABLE_PACK_ASSET_KINDS",
511
+ descriptor.kind,
512
+ sourcePath
513
+ );
514
+ }
515
+ if (descriptor.name !== void 0 && typeof descriptor.name !== "string") {
516
+ return invalid(
517
+ `$.assets[${JSON.stringify(sourceKey)}].name`,
518
+ "a string when present",
519
+ descriptor.name,
520
+ sourcePath
521
+ );
522
+ }
523
+ const guid = guidKey(descriptor.guid);
524
+ if (guid === packageGuid || localGuids.has(guid)) {
525
+ return invalid(
526
+ `$.assets[${JSON.stringify(sourceKey)}].guid`,
527
+ "a GUID unique within the package and distinct from packageId",
528
+ descriptor.guid,
529
+ sourcePath
530
+ );
531
+ }
532
+ localGuids.add(guid);
533
+ }
534
+ const externalGuids = /* @__PURE__ */ new Set();
535
+ for (const [alias, guidValue] of Object.entries(value.externalAssets)) {
536
+ if (alias.trim().length === 0) {
537
+ return invalid("$.externalAssets", "non-empty alias object keys", alias, sourcePath);
538
+ }
539
+ if (!isAssetGuid(guidValue)) {
540
+ return invalid(
541
+ `$.externalAssets[${JSON.stringify(alias)}]`,
542
+ "a 16-byte AssetGuid",
543
+ guidValue,
544
+ sourcePath
545
+ );
546
+ }
547
+ const guid = guidKey(guidValue);
548
+ if (guid === packageGuid || localGuids.has(guid) || externalGuids.has(guid)) {
549
+ return invalid(
550
+ `$.externalAssets[${JSON.stringify(alias)}]`,
551
+ "a unique foreign GUID not owned by this package",
552
+ guidValue,
553
+ sourcePath
554
+ );
555
+ }
556
+ externalGuids.add(guid);
557
+ }
558
+ return ok(freezeDefinition(value));
559
+ }
560
+ function projectScriptablePackMeta(definition, source) {
561
+ const subAssets = Object.entries(definition.assets).sort(([left], [right]) => left.localeCompare(right)).map(([sourceKey, descriptor], sourceIndex) => ({
562
+ guid: guidKey(descriptor.guid),
563
+ sourceIndex,
564
+ sourceKey,
565
+ kind: descriptor.kind,
566
+ ...descriptor.name === void 0 ? {} : { name: descriptor.name }
567
+ }));
568
+ const externalAssets = Object.entries(definition.externalAssets).sort(([left], [right]) => left.localeCompare(right)).map(([alias, guid]) => ({ alias, guid: guidKey(guid) }));
569
+ return {
570
+ schemaVersion: "1.0.0",
571
+ kind: "external-asset-package",
572
+ packageId: guidKey(definition.packageId),
573
+ ...definition.name === void 0 ? {} : { name: definition.name },
574
+ importer: "pack-ts",
575
+ source,
576
+ importSettings: { contractVersion: "1.0.0", externalAssets },
577
+ subAssets
578
+ };
579
+ }
580
+
581
+ export { SCRIPTABLE_PACK_ASSET_KINDS, SOURCE_AUTHORING_OPERATION_DESCRIPTORS, createScriptablePackAuthoringGateway, isScriptablePackAssetKind, projectScriptablePackMeta, validateScriptablePackDefinition };
582
+ //# sourceMappingURL=scriptable-pack.mjs.map
583
+ //# sourceMappingURL=scriptable-pack.mjs.map