@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.
- package/LICENSE +202 -0
- package/README.md +370 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/__tests__/ai-recovery.unit.test.d.ts +2 -0
- package/dist/__tests__/ai-recovery.unit.test.d.ts.map +1 -0
- package/dist/__tests__/artifact-path.test.d.ts +2 -0
- package/dist/__tests__/artifact-path.test.d.ts.map +1 -0
- package/dist/__tests__/asset-evidence-error-hints.test.d.ts +2 -0
- package/dist/__tests__/asset-evidence-error-hints.test.d.ts.map +1 -0
- package/dist/__tests__/asset-evidence-lifecycle.test.d.ts +2 -0
- package/dist/__tests__/asset-evidence-lifecycle.test.d.ts.map +1 -0
- package/dist/__tests__/asset-evidence-schema.test.d.ts +2 -0
- package/dist/__tests__/asset-evidence-schema.test.d.ts.map +1 -0
- package/dist/__tests__/atlas-cli-region-mismatch.test.d.ts +2 -0
- package/dist/__tests__/atlas-cli-region-mismatch.test.d.ts.map +1 -0
- package/dist/__tests__/atlas-error-code-owner.test-d.d.ts +2 -0
- package/dist/__tests__/atlas-error-code-owner.test-d.d.ts.map +1 -0
- package/dist/__tests__/cli-asset-evidence.integration.test.d.ts +2 -0
- package/dist/__tests__/cli-asset-evidence.integration.test.d.ts.map +1 -0
- package/dist/__tests__/cli.unit.test.d.ts +2 -0
- package/dist/__tests__/cli.unit.test.d.ts.map +1 -0
- package/dist/__tests__/evidence-source-inventory.unit.test.d.ts +2 -0
- package/dist/__tests__/evidence-source-inventory.unit.test.d.ts.map +1 -0
- package/dist/__tests__/guid-collision.unit.test.d.ts +2 -0
- package/dist/__tests__/guid-collision.unit.test.d.ts.map +1 -0
- package/dist/__tests__/guid-validator-surface.unit.test.d.ts +2 -0
- package/dist/__tests__/guid-validator-surface.unit.test.d.ts.map +1 -0
- package/dist/__tests__/load-asset-config.test.d.ts +2 -0
- package/dist/__tests__/load-asset-config.test.d.ts.map +1 -0
- package/dist/__tests__/material-cook-dependencies.unit.test.d.ts +2 -0
- package/dist/__tests__/material-cook-dependencies.unit.test.d.ts.map +1 -0
- package/dist/__tests__/material-cook-receipt.unit.test.d.ts +2 -0
- package/dist/__tests__/material-cook-receipt.unit.test.d.ts.map +1 -0
- package/dist/__tests__/material-cook-schema.unit.test.d.ts +2 -0
- package/dist/__tests__/material-cook-schema.unit.test.d.ts.map +1 -0
- package/dist/__tests__/mesh-bin-consumer-surface.unit.test.d.ts +2 -0
- package/dist/__tests__/mesh-bin-consumer-surface.unit.test.d.ts.map +1 -0
- package/dist/__tests__/mesh-bin-contract.unit.test.d.ts +2 -0
- package/dist/__tests__/mesh-bin-contract.unit.test.d.ts.map +1 -0
- package/dist/__tests__/meta-schema-optional.test.d.ts +2 -0
- package/dist/__tests__/meta-schema-optional.test.d.ts.map +1 -0
- package/dist/__tests__/meta-source-overrides.unit.test.d.ts +2 -0
- package/dist/__tests__/meta-source-overrides.unit.test.d.ts.map +1 -0
- package/dist/__tests__/native-cooker-registry.test.d.ts +2 -0
- package/dist/__tests__/native-cooker-registry.test.d.ts.map +1 -0
- package/dist/__tests__/offline-evidence-artifact-verification-owner.test-d.d.ts +2 -0
- package/dist/__tests__/offline-evidence-artifact-verification-owner.test-d.d.ts.map +1 -0
- package/dist/__tests__/offline-evidence.integration.test.d.ts +2 -0
- package/dist/__tests__/offline-evidence.integration.test.d.ts.map +1 -0
- package/dist/__tests__/pack-v2-fixture-migration.test.d.ts +2 -0
- package/dist/__tests__/pack-v2-fixture-migration.test.d.ts.map +1 -0
- package/dist/__tests__/pack-v2-schema.test.d.ts +2 -0
- package/dist/__tests__/pack-v2-schema.test.d.ts.map +1 -0
- package/dist/__tests__/pack.unit.test.d.ts +2 -0
- package/dist/__tests__/pack.unit.test.d.ts.map +1 -0
- package/dist/__tests__/producer-contract-schema.unit.test.d.ts +2 -0
- package/dist/__tests__/producer-contract-schema.unit.test.d.ts.map +1 -0
- package/dist/__tests__/resolve-asset-source.test.d.ts +2 -0
- package/dist/__tests__/resolve-asset-source.test.d.ts.map +1 -0
- package/dist/__tests__/runtime-projection.unit.test.d.ts +2 -0
- package/dist/__tests__/runtime-projection.unit.test.d.ts.map +1 -0
- package/dist/__tests__/scanner-inventory.test.d.ts +2 -0
- package/dist/__tests__/scanner-inventory.test.d.ts.map +1 -0
- package/dist/__tests__/scanner-mount-cycle.test.d.ts +2 -0
- package/dist/__tests__/scanner-mount-cycle.test.d.ts.map +1 -0
- package/dist/__tests__/scriptable-pack-cli.integration.test.d.ts +2 -0
- package/dist/__tests__/scriptable-pack-cli.integration.test.d.ts.map +1 -0
- package/dist/__tests__/scriptable-pack-ddc-key.unit.test.d.ts +2 -0
- package/dist/__tests__/scriptable-pack-ddc-key.unit.test.d.ts.map +1 -0
- package/dist/__tests__/scriptable-pack.test-d.d.ts +2 -0
- package/dist/__tests__/scriptable-pack.test-d.d.ts.map +1 -0
- package/dist/__tests__/scriptable-pack.unit.test.d.ts +2 -0
- package/dist/__tests__/scriptable-pack.unit.test.d.ts.map +1 -0
- package/dist/__tests__/topology-actions.unit.test.d.ts +2 -0
- package/dist/__tests__/topology-actions.unit.test.d.ts.map +1 -0
- package/dist/__tests__/topology.unit.test.d.ts +2 -0
- package/dist/__tests__/topology.unit.test.d.ts.map +1 -0
- package/dist/artifact-path.d.ts +9 -0
- package/dist/artifact-path.d.ts.map +1 -0
- package/dist/atlas/run-atlas.d.ts +8 -0
- package/dist/atlas/run-atlas.d.ts.map +1 -0
- package/dist/atlas/shelf-pack.d.ts +55 -0
- package/dist/atlas/shelf-pack.d.ts.map +1 -0
- package/dist/bridge.d.ts +2 -0
- package/dist/bridge.d.ts.map +1 -0
- package/dist/bridge.mjs +3 -0
- package/dist/bridge.mjs.map +1 -0
- package/dist/builtin.d.ts +24 -0
- package/dist/builtin.d.ts.map +1 -0
- package/dist/cli-asset.d.ts +22 -0
- package/dist/cli-asset.d.ts.map +1 -0
- package/dist/cli-asset.mjs +9950 -0
- package/dist/cli-asset.mjs.map +1 -0
- package/dist/config.d.ts +6 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.mjs +29 -0
- package/dist/config.mjs.map +1 -0
- package/dist/deriveAssetName.d.ts +15 -0
- package/dist/deriveAssetName.d.ts.map +1 -0
- package/dist/errors.d.ts +30 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.mjs +19 -0
- package/dist/errors.mjs.map +1 -0
- package/dist/evidence/material-cook.d.ts +70 -0
- package/dist/evidence/material-cook.d.ts.map +1 -0
- package/dist/evidence/offline-evidence.d.ts +25 -0
- package/dist/evidence/offline-evidence.d.ts.map +1 -0
- package/dist/evidence/source-inventory.d.ts +29 -0
- package/dist/evidence/source-inventory.d.ts.map +1 -0
- package/dist/guid.d.ts +45 -0
- package/dist/guid.d.ts.map +1 -0
- package/dist/guid.mjs +94 -0
- package/dist/guid.mjs.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.mjs +8475 -0
- package/dist/index.mjs.map +1 -0
- package/dist/material/artifact-writer.d.ts +14 -0
- package/dist/material/artifact-writer.d.ts.map +1 -0
- package/dist/mesh-bin-contract.d.ts +36 -0
- package/dist/mesh-bin-contract.d.ts.map +1 -0
- package/dist/name.mjs +22 -0
- package/dist/name.mjs.map +1 -0
- package/dist/native-cooker-registry.d.ts +28 -0
- package/dist/native-cooker-registry.d.ts.map +1 -0
- package/dist/native-cooker.d.ts +3 -0
- package/dist/native-cooker.d.ts.map +1 -0
- package/dist/native-cooker.mjs +105 -0
- package/dist/native-cooker.mjs.map +1 -0
- package/dist/producer-contract.d.ts +19 -0
- package/dist/producer-contract.d.ts.map +1 -0
- package/dist/resolve-asset-source.d.ts +4 -0
- package/dist/resolve-asset-source.d.ts.map +1 -0
- package/dist/resolve-asset-source.mjs +99 -0
- package/dist/resolve-asset-source.mjs.map +1 -0
- package/dist/runtime-projection.d.ts +14 -0
- package/dist/runtime-projection.d.ts.map +1 -0
- package/dist/scanner.d.ts +80 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.mjs +9015 -0
- package/dist/scanner.mjs.map +1 -0
- package/dist/schema-compiled.d.ts +12 -0
- package/dist/schema-compiled.d.ts.map +1 -0
- package/dist/schema.mjs +7369 -0
- package/dist/schema.mjs.map +1 -0
- package/dist/scriptable-pack-node.d.ts +67 -0
- package/dist/scriptable-pack-node.d.ts.map +1 -0
- package/dist/scriptable-pack-node.mjs +1590 -0
- package/dist/scriptable-pack-node.mjs.map +1 -0
- package/dist/scriptable-pack-worker.d.ts +2 -0
- package/dist/scriptable-pack-worker.d.ts.map +1 -0
- package/dist/scriptable-pack-worker.mjs +223 -0
- package/dist/scriptable-pack-worker.mjs.map +1 -0
- package/dist/scriptable-pack.d.ts +525 -0
- package/dist/scriptable-pack.d.ts.map +1 -0
- package/dist/scriptable-pack.mjs +583 -0
- package/dist/scriptable-pack.mjs.map +1 -0
- package/dist/topology.d.ts +10 -0
- package/dist/topology.d.ts.map +1 -0
- package/package.json +129 -0
- package/schema/meta.schema.json +173 -0
- package/schema/pack.schema.json +232 -0
- package/src/__tests__/ai-recovery.unit.test.ts +114 -0
- package/src/__tests__/artifact-path.test.ts +41 -0
- package/src/__tests__/asset-evidence-error-hints.test.ts +46 -0
- package/src/__tests__/asset-evidence-lifecycle.test.ts +104 -0
- package/src/__tests__/asset-evidence-schema.test.ts +86 -0
- package/src/__tests__/atlas-cli-region-mismatch.test.ts +134 -0
- package/src/__tests__/atlas-error-code-owner.test-d.ts +23 -0
- package/src/__tests__/cli-asset-evidence.integration.test.ts +172 -0
- package/src/__tests__/cli.unit.test.ts +448 -0
- package/src/__tests__/evidence-source-inventory.unit.test.ts +37 -0
- package/src/__tests__/guid-collision.unit.test.ts +112 -0
- package/src/__tests__/guid-validator-surface.unit.test.ts +20 -0
- package/src/__tests__/load-asset-config.test.ts +121 -0
- package/src/__tests__/material-cook-dependencies.unit.test.ts +45 -0
- package/src/__tests__/material-cook-receipt.unit.test.ts +91 -0
- package/src/__tests__/material-cook-schema.unit.test.ts +98 -0
- package/src/__tests__/mesh-bin-consumer-surface.unit.test.ts +21 -0
- package/src/__tests__/mesh-bin-contract.unit.test.ts +32 -0
- package/src/__tests__/meta-schema-optional.test.ts +116 -0
- package/src/__tests__/meta-source-overrides.unit.test.ts +71 -0
- package/src/__tests__/native-cooker-registry.test.ts +64 -0
- package/src/__tests__/offline-evidence-artifact-verification-owner.test-d.ts +64 -0
- package/src/__tests__/offline-evidence.integration.test.ts +106 -0
- package/src/__tests__/pack-v2-fixture-migration.test.ts +64 -0
- package/src/__tests__/pack-v2-schema.test.ts +142 -0
- package/src/__tests__/pack.unit.test.ts +2218 -0
- package/src/__tests__/producer-contract-schema.unit.test.ts +92 -0
- package/src/__tests__/resolve-asset-source.test.ts +121 -0
- package/src/__tests__/runtime-projection.unit.test.ts +87 -0
- package/src/__tests__/scanner-inventory.test.ts +72 -0
- package/src/__tests__/scanner-mount-cycle.test.ts +232 -0
- package/src/__tests__/scriptable-pack-cli.integration.test.ts +47 -0
- package/src/__tests__/scriptable-pack-ddc-key.unit.test.ts +63 -0
- package/src/__tests__/scriptable-pack.test-d.ts +131 -0
- package/src/__tests__/scriptable-pack.unit.test.ts +747 -0
- package/src/__tests__/topology-actions.unit.test.ts +94 -0
- package/src/__tests__/topology.unit.test.ts +85 -0
- package/src/artifact-path.ts +69 -0
- package/src/atlas/run-atlas.ts +358 -0
- package/src/atlas/shelf-pack.ts +176 -0
- package/src/atlas/upng-ambient.d.ts +13 -0
- package/src/bridge.ts +2 -0
- package/src/builtin.ts +79 -0
- package/src/cli-asset.ts +590 -0
- package/src/config.ts +36 -0
- package/src/deriveAssetName.ts +42 -0
- package/src/errors.ts +47 -0
- package/src/evidence/material-cook.ts +332 -0
- package/src/evidence/offline-evidence.ts +90 -0
- package/src/evidence/source-inventory.ts +193 -0
- package/src/guid.ts +99 -0
- package/src/index.ts +104 -0
- package/src/material/artifact-writer.ts +26 -0
- package/src/mesh-bin-contract.ts +150 -0
- package/src/native-cooker-registry.ts +163 -0
- package/src/native-cooker.ts +2 -0
- package/src/producer-contract.ts +277 -0
- package/src/resolve-asset-source.ts +93 -0
- package/src/runtime-projection.ts +100 -0
- package/src/scanner.ts +716 -0
- package/src/schema/material-cook.schema.json +79 -0
- package/src/schema-compiled.ts +238 -0
- package/src/scriptable-pack-node.ts +1390 -0
- package/src/scriptable-pack-worker.ts +306 -0
- package/src/scriptable-pack.ts +884 -0
- 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
|