@forgeax/engine-import 0.1.23 → 0.1.25
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/README.md +5 -5
- package/dist/__tests__/scriptable-pack-build.unit.test.d.ts +2 -0
- package/dist/__tests__/scriptable-pack-build.unit.test.d.ts.map +1 -0
- package/dist/build-production.d.ts.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +284 -60
- package/dist/index.mjs.map +1 -1
- package/dist/{parameterized-scriptable-pack.d.ts → scriptable-pack-build.d.ts} +20 -15
- package/dist/scriptable-pack-build.d.ts.map +1 -0
- package/dist/scriptable-pack-host.d.ts +15 -13
- package/dist/scriptable-pack-host.d.ts.map +1 -1
- package/dist/scriptable-pack.d.ts +2 -1
- package/dist/scriptable-pack.d.ts.map +1 -1
- package/dist/source-package-publication.d.ts +7 -0
- package/dist/source-package-publication.d.ts.map +1 -1
- package/package.json +8 -8
- package/src/__tests__/{parameterized-scriptable-pack.unit.test.ts → scriptable-pack-build.unit.test.ts} +11 -14
- package/src/__tests__/scriptable-pack-host.unit.test.ts +53 -5
- package/src/__tests__/scriptable-pack-output-producers.unit.test.ts +4 -5
- package/src/__tests__/source-package-publication.integration.test.ts +141 -0
- package/src/build-production.ts +45 -50
- package/src/index.ts +17 -16
- package/src/{parameterized-scriptable-pack.ts → scriptable-pack-build.ts} +91 -27
- package/src/scriptable-pack-host.ts +48 -40
- package/src/scriptable-pack.ts +2 -1
- package/src/source-package-publication.ts +242 -10
- package/dist/__tests__/parameterized-scriptable-pack.unit.test.d.ts +0 -2
- package/dist/__tests__/parameterized-scriptable-pack.unit.test.d.ts.map +0 -1
- package/dist/parameterized-scriptable-pack.d.ts.map +0 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BUILTIN_MESH_ASSETS } from '@forgeax/engine-pack/builtin';
|
|
2
|
+
import { type NativeCooker, NativeCookerRegistry } from '@forgeax/engine-pack/native-cooker';
|
|
2
3
|
import {
|
|
3
|
-
type
|
|
4
|
+
type AnyScriptablePackDefinition,
|
|
4
5
|
AssetGuid,
|
|
5
6
|
isScriptablePackAssetKind,
|
|
6
7
|
isValidPackSourceKey,
|
|
@@ -12,6 +13,7 @@ import {
|
|
|
12
13
|
type PackParameterValue,
|
|
13
14
|
resolvePackParameterValues,
|
|
14
15
|
} from '@forgeax/engine-pack/source';
|
|
16
|
+
import { DEFAULT_STANDARD_SURFACE_MODULE } from '@forgeax/engine-shader';
|
|
15
17
|
import type {
|
|
16
18
|
Asset,
|
|
17
19
|
AssetGuid as AssetGuidType,
|
|
@@ -28,16 +30,16 @@ import {
|
|
|
28
30
|
import type {
|
|
29
31
|
AssetOutputProducer,
|
|
30
32
|
AssetOutputProducerRegistry,
|
|
33
|
+
PackBuildProduct,
|
|
31
34
|
ScriptablePackAssetSnapshotSource,
|
|
32
|
-
ScriptablePackBuildProduct,
|
|
33
35
|
ScriptablePackDomainError,
|
|
34
36
|
ScriptablePackExternalEvidence,
|
|
35
37
|
ScriptablePackSourceClosureEntry,
|
|
36
38
|
ScriptablePackStagedOutput,
|
|
37
39
|
} from './scriptable-pack.js';
|
|
38
40
|
|
|
39
|
-
export interface
|
|
40
|
-
readonly definition:
|
|
41
|
+
export interface ScriptablePackBuildOptions {
|
|
42
|
+
readonly definition: AnyScriptablePackDefinition;
|
|
41
43
|
readonly sourcePath: string;
|
|
42
44
|
/** Instance identity. Omitted for a root source and defaults to definition.packageId. */
|
|
43
45
|
readonly subjectPackageId?: PackageId;
|
|
@@ -47,6 +49,8 @@ export interface ParameterizedScriptablePackBuildOptions {
|
|
|
47
49
|
readonly inheritedValues?: Readonly<Record<string, PackParameterValue>>;
|
|
48
50
|
readonly assetSource?: ScriptablePackAssetSnapshotSource;
|
|
49
51
|
readonly outputs: AssetOutputProducerRegistry;
|
|
52
|
+
/** Optional build-time cookers for authored producer outputs that need artifacts. */
|
|
53
|
+
readonly cookers?: readonly NativeCooker[];
|
|
50
54
|
readonly sourceClosure?: readonly ScriptablePackSourceClosureEntry[];
|
|
51
55
|
readonly authoringContractVersion?: string;
|
|
52
56
|
/** Known published GUIDs used for the optional global reference gate. */
|
|
@@ -56,12 +60,12 @@ export interface ParameterizedScriptablePackBuildOptions {
|
|
|
56
60
|
readonly publication?: AssetPublicationEnvelope;
|
|
57
61
|
}
|
|
58
62
|
|
|
59
|
-
export interface
|
|
63
|
+
export interface ScriptablePackBuildProduct extends PackBuildProduct {
|
|
60
64
|
readonly publication?: AssetPublicationEnvelope;
|
|
61
65
|
}
|
|
62
66
|
|
|
63
|
-
export type
|
|
64
|
-
|
|
67
|
+
export type ScriptablePackBuildResult = Result<
|
|
68
|
+
ScriptablePackBuildProduct,
|
|
65
69
|
| PackAuthoringError
|
|
66
70
|
| ScriptablePackDomainError
|
|
67
71
|
| AssetError
|
|
@@ -89,6 +93,23 @@ function isAsset(value: unknown): value is Asset {
|
|
|
89
93
|
return record(value) && typeof value.kind === 'string' && isScriptablePackAssetKind(value.kind);
|
|
90
94
|
}
|
|
91
95
|
|
|
96
|
+
function needsMaterialCook(asset: Asset): asset is Extract<Asset, { readonly kind: 'material' }> {
|
|
97
|
+
if (asset.kind !== 'material' || !Array.isArray(asset.passes)) return false;
|
|
98
|
+
return asset.passes.some((pass) => {
|
|
99
|
+
const module = pass.program.module;
|
|
100
|
+
const surface = pass.program.moduleSlots?.surface;
|
|
101
|
+
return (
|
|
102
|
+
surface !== undefined &&
|
|
103
|
+
surface !== DEFAULT_STANDARD_SURFACE_MODULE &&
|
|
104
|
+
(module === 'forgeax_material::standard' ||
|
|
105
|
+
module === 'forgeax::default-standard-pbr' ||
|
|
106
|
+
module === 'forgeax_material::pbr-skin' ||
|
|
107
|
+
module === 'forgeax::pbr-skin' ||
|
|
108
|
+
module === 'forgeax::default-standard-pbr-skin')
|
|
109
|
+
);
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
92
113
|
function clone<T>(value: T): T {
|
|
93
114
|
return structuredClone(value);
|
|
94
115
|
}
|
|
@@ -289,9 +310,9 @@ function normalizedGuidSet(value: ReadonlySet<string> | undefined): Set<string>
|
|
|
289
310
|
* Execute a v2 Pack source and project its dynamic output map through the
|
|
290
311
|
* existing importer producers. No output GUID or output manifest is read.
|
|
291
312
|
*/
|
|
292
|
-
export async function
|
|
293
|
-
options:
|
|
294
|
-
): Promise<
|
|
313
|
+
export async function buildScriptablePack(
|
|
314
|
+
options: ScriptablePackBuildOptions,
|
|
315
|
+
): Promise<ScriptablePackBuildResult> {
|
|
295
316
|
const subjectPackageId = options.subjectPackageId ?? options.definition.packageId;
|
|
296
317
|
const availableGuids = normalizedGuidSet(options.availableGuids);
|
|
297
318
|
const observed = observedReader(options.assetSource);
|
|
@@ -319,8 +340,8 @@ export async function buildParameterizedScriptablePack(
|
|
|
319
340
|
PackageId.format(options.definition.packageId).toLowerCase()
|
|
320
341
|
) {
|
|
321
342
|
return err({
|
|
322
|
-
code: 'pack-parent-
|
|
323
|
-
expected: 'a
|
|
343
|
+
code: 'pack-parent-has-no-parameters',
|
|
344
|
+
expected: 'a ScriptablePack source with parameters for an independent instance packageId',
|
|
324
345
|
hint: 'use clone for a zero-parameter Pack instead of building it as an instance',
|
|
325
346
|
detail: {
|
|
326
347
|
sourcePath: options.sourcePath,
|
|
@@ -384,6 +405,9 @@ export async function buildParameterizedScriptablePack(
|
|
|
384
405
|
const imported: ImportedAsset<unknown>[] = [];
|
|
385
406
|
const stagedOutputs: ScriptablePackStagedOutput[] = [];
|
|
386
407
|
const localGuids = new Set<string>();
|
|
408
|
+
const materialCookerRegistry = new NativeCookerRegistry();
|
|
409
|
+
for (const cooker of options.cookers ?? []) materialCookerRegistry.register(cooker);
|
|
410
|
+
const nativeFingerprints = new Map<string, string>();
|
|
387
411
|
for (const sourceKey of Object.keys(built.value).sort()) {
|
|
388
412
|
if (!isValidPackSourceKey(sourceKey))
|
|
389
413
|
return err(sourceKeyFailure(options.sourcePath, sourceKey));
|
|
@@ -459,12 +483,40 @@ export async function buildParameterizedScriptablePack(
|
|
|
459
483
|
const invalidProduct = productError(options.sourcePath, sourceKey, producer, produced.value);
|
|
460
484
|
if (invalidProduct !== undefined) return err(invalidProduct);
|
|
461
485
|
const product = produced.value as ImportAssetProduct<unknown>;
|
|
486
|
+
let payload = product.payload;
|
|
487
|
+
let artifacts = product.artifacts;
|
|
488
|
+
if (needsMaterialCook(asset) && materialCookerRegistry.get('material') !== undefined) {
|
|
489
|
+
const cooked = await materialCookerRegistry.runDraft('material', {
|
|
490
|
+
guid,
|
|
491
|
+
source: asset,
|
|
492
|
+
sourceKey,
|
|
493
|
+
sourcePath: options.sourcePath,
|
|
494
|
+
refs: product.refs.map((reference) => reference.guid),
|
|
495
|
+
});
|
|
496
|
+
if (!cooked.ok) return err(cooked.error);
|
|
497
|
+
if (cooked.value.guid.toLowerCase() !== normalizedGuid) {
|
|
498
|
+
return err({
|
|
499
|
+
code: 'pack-source-output-invalid',
|
|
500
|
+
expected: 'the authored material cooker to preserve the derived AssetGuid',
|
|
501
|
+
hint: 'repair the native material cooker output GUID and rebuild the Pack',
|
|
502
|
+
detail: {
|
|
503
|
+
sourcePath: options.sourcePath,
|
|
504
|
+
sourceKey,
|
|
505
|
+
expectedGuid: guid,
|
|
506
|
+
actualGuid: cooked.value.guid,
|
|
507
|
+
},
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
payload = cooked.value.payload;
|
|
511
|
+
artifacts = cooked.value.artifacts;
|
|
512
|
+
nativeFingerprints.set(sourceKey, cooked.value.inputFingerprint);
|
|
513
|
+
}
|
|
462
514
|
imported.push({
|
|
463
515
|
guid,
|
|
464
516
|
kind: asset.kind,
|
|
465
|
-
payload
|
|
517
|
+
payload,
|
|
466
518
|
refs: product.refs,
|
|
467
|
-
artifacts
|
|
519
|
+
artifacts,
|
|
468
520
|
});
|
|
469
521
|
stagedOutputs.push({
|
|
470
522
|
guid: AssetGuid.derive(subjectPackageId, sourceKey),
|
|
@@ -499,7 +551,7 @@ export async function buildParameterizedScriptablePack(
|
|
|
499
551
|
digest: read.digest,
|
|
500
552
|
}),
|
|
501
553
|
);
|
|
502
|
-
const
|
|
554
|
+
const authoredInputFingerprint = await digest({
|
|
503
555
|
packageId: PackageId.format(subjectPackageId),
|
|
504
556
|
sourcePath: options.sourcePath,
|
|
505
557
|
sourceClosure: options.sourceClosure ?? [],
|
|
@@ -509,9 +561,18 @@ export async function buildParameterizedScriptablePack(
|
|
|
509
561
|
usage,
|
|
510
562
|
digest: evidenceDigest,
|
|
511
563
|
})),
|
|
512
|
-
authoringContractVersion: options.authoringContractVersion ?? '
|
|
564
|
+
authoringContractVersion: options.authoringContractVersion ?? 'scriptable-pack/1',
|
|
513
565
|
producerVersions: options.outputs.versions(),
|
|
514
566
|
});
|
|
567
|
+
const inputFingerprint =
|
|
568
|
+
nativeFingerprints.size === 0
|
|
569
|
+
? authoredInputFingerprint
|
|
570
|
+
: await digest({
|
|
571
|
+
sourceRevision: authoredInputFingerprint,
|
|
572
|
+
nativeCookers: [...nativeFingerprints.entries()].sort(([left], [right]) =>
|
|
573
|
+
left.localeCompare(right),
|
|
574
|
+
),
|
|
575
|
+
});
|
|
515
576
|
const refs = imported.flatMap((asset) => asset.refs);
|
|
516
577
|
const artifacts = Object.fromEntries(
|
|
517
578
|
imported.flatMap((asset) =>
|
|
@@ -543,8 +604,8 @@ export async function buildParameterizedScriptablePack(
|
|
|
543
604
|
});
|
|
544
605
|
}
|
|
545
606
|
|
|
546
|
-
export interface
|
|
547
|
-
readonly definition:
|
|
607
|
+
export interface ScriptablePackBuildWorkItem {
|
|
608
|
+
readonly definition: AnyScriptablePackDefinition;
|
|
548
609
|
readonly sourcePath: string;
|
|
549
610
|
readonly subjectPackageId?: PackageId;
|
|
550
611
|
readonly values?: Readonly<Record<string, unknown>>;
|
|
@@ -552,18 +613,20 @@ export interface ParameterizedScriptablePackWorkItem {
|
|
|
552
613
|
readonly sourceClosure?: readonly ScriptablePackSourceClosureEntry[];
|
|
553
614
|
}
|
|
554
615
|
|
|
555
|
-
export interface
|
|
556
|
-
readonly subjects: readonly
|
|
616
|
+
export interface ScriptablePackBuildWorklistOptions {
|
|
617
|
+
readonly subjects: readonly ScriptablePackBuildWorkItem[];
|
|
557
618
|
readonly outputs: AssetOutputProducerRegistry;
|
|
619
|
+
/** Optional build-time cookers forwarded to each authored Pack subject. */
|
|
620
|
+
readonly cookers?: readonly NativeCooker[];
|
|
558
621
|
readonly assetSource?: ScriptablePackAssetSnapshotSource;
|
|
559
622
|
readonly availableGuids?: ReadonlySet<string>;
|
|
560
623
|
readonly incomingRefs?: ReadonlyMap<string, readonly string[]>;
|
|
561
624
|
readonly maxPasses?: number;
|
|
562
625
|
}
|
|
563
626
|
|
|
564
|
-
export interface
|
|
627
|
+
export interface ScriptablePackBuildWorklistProduct {
|
|
565
628
|
readonly products: readonly TerminalImportProduct<unknown>[];
|
|
566
|
-
readonly buildProducts: readonly
|
|
629
|
+
readonly buildProducts: readonly ScriptablePackBuildProduct[];
|
|
567
630
|
readonly stagedOutputs: readonly ScriptablePackStagedOutput[];
|
|
568
631
|
readonly iterations: number;
|
|
569
632
|
}
|
|
@@ -597,11 +660,11 @@ function stagedSource(
|
|
|
597
660
|
}
|
|
598
661
|
|
|
599
662
|
/** Build subjects in stable passes; content reads may wait for a later subject. */
|
|
600
|
-
export async function
|
|
601
|
-
options:
|
|
663
|
+
export async function buildScriptablePackWorklist(
|
|
664
|
+
options: ScriptablePackBuildWorklistOptions,
|
|
602
665
|
): Promise<
|
|
603
666
|
Result<
|
|
604
|
-
|
|
667
|
+
ScriptablePackBuildWorklistProduct,
|
|
605
668
|
| PackAuthoringError
|
|
606
669
|
| ScriptablePackDomainError
|
|
607
670
|
| AssetError
|
|
@@ -621,7 +684,7 @@ export async function buildParameterizedScriptablePackWorklist(
|
|
|
621
684
|
orderedSubjects.map((subject, index) => [`${index}:${subject.sourcePath}`, subject]),
|
|
622
685
|
);
|
|
623
686
|
const staged = new Map<string, ScriptablePackStagedOutput>();
|
|
624
|
-
const results = new Map<string,
|
|
687
|
+
const results = new Map<string, ScriptablePackBuildProduct>();
|
|
625
688
|
const availableGuids = new Set([
|
|
626
689
|
...(normalizedGuidSet(options.availableGuids) ?? []),
|
|
627
690
|
...BUILTIN_MESH_ASSETS.map((asset) => asset.guid.toLowerCase()),
|
|
@@ -632,7 +695,7 @@ export async function buildParameterizedScriptablePackWorklist(
|
|
|
632
695
|
let progress = false;
|
|
633
696
|
const waiting = new Set<string>();
|
|
634
697
|
for (const [key, subject] of pending) {
|
|
635
|
-
const result = await
|
|
698
|
+
const result = await buildScriptablePack({
|
|
636
699
|
definition: subject.definition,
|
|
637
700
|
sourcePath: subject.sourcePath,
|
|
638
701
|
...(subject.subjectPackageId === undefined
|
|
@@ -644,6 +707,7 @@ export async function buildParameterizedScriptablePackWorklist(
|
|
|
644
707
|
: { inheritedValues: subject.inheritedValues }),
|
|
645
708
|
...(subject.sourceClosure === undefined ? {} : { sourceClosure: subject.sourceClosure }),
|
|
646
709
|
outputs: options.outputs,
|
|
710
|
+
...(options.cookers === undefined ? {} : { cookers: options.cookers }),
|
|
647
711
|
assetSource: stagedSource(staged, options.assetSource),
|
|
648
712
|
availableGuids: new Set([...availableGuids, ...staged.keys()]),
|
|
649
713
|
deferReferenceValidation: true,
|
|
@@ -20,10 +20,10 @@ import type {
|
|
|
20
20
|
ScanSourceDeclaration,
|
|
21
21
|
} from '@forgeax/engine-pack/scanner';
|
|
22
22
|
import {
|
|
23
|
-
type
|
|
23
|
+
type AnyScriptablePackDefinition,
|
|
24
24
|
type DirectPackAssetProjection,
|
|
25
25
|
isScriptablePackAssetKind,
|
|
26
|
-
|
|
26
|
+
parsePackSourceJson,
|
|
27
27
|
projectDirectPackJson,
|
|
28
28
|
projectScriptablePackSceneComponents,
|
|
29
29
|
type ScriptablePackSourceClosureEntry,
|
|
@@ -45,17 +45,17 @@ import { AssetError, err, ok } from '@forgeax/engine-types';
|
|
|
45
45
|
import type { DdcPack, ImportRunnerFs, RunImportMeta } from './import-runner.js';
|
|
46
46
|
import type { ImporterRegistry } from './importer-registry.js';
|
|
47
47
|
import { projectImportProductForBuild } from './pack-projection.js';
|
|
48
|
-
import {
|
|
49
|
-
buildParameterizedScriptablePack,
|
|
50
|
-
buildParameterizedScriptablePackWorklist,
|
|
51
|
-
type ParameterizedScriptablePackBuildProduct,
|
|
52
|
-
type ParameterizedScriptablePackWorkItem,
|
|
53
|
-
} from './parameterized-scriptable-pack.js';
|
|
54
48
|
import type {
|
|
55
49
|
ScriptablePackAssetSnapshotSource,
|
|
56
50
|
ScriptablePackDomainError,
|
|
57
51
|
ScriptablePackStagedOutput,
|
|
58
52
|
} from './scriptable-pack.js';
|
|
53
|
+
import {
|
|
54
|
+
buildScriptablePack,
|
|
55
|
+
buildScriptablePackWorklist,
|
|
56
|
+
type ScriptablePackBuildProduct,
|
|
57
|
+
type ScriptablePackBuildWorkItem,
|
|
58
|
+
} from './scriptable-pack-build.js';
|
|
59
59
|
import {
|
|
60
60
|
createPreExternalizedSceneAssetOutputProducer,
|
|
61
61
|
createStandardAssetOutputProducerRegistry,
|
|
@@ -64,15 +64,15 @@ import { produceSourcePackage } from './source-package.js';
|
|
|
64
64
|
|
|
65
65
|
type FinalizedPackageTransport = Awaited<ReturnType<typeof finalizePackageTransportSource>>;
|
|
66
66
|
|
|
67
|
-
export interface
|
|
67
|
+
export interface ScriptablePackInput {
|
|
68
68
|
readonly sourcePath: string;
|
|
69
69
|
readonly displaySourcePath: string;
|
|
70
|
-
readonly definition:
|
|
70
|
+
readonly definition: AnyScriptablePackDefinition;
|
|
71
71
|
readonly sourceClosure: readonly ScriptablePackSourceClosureEntry[];
|
|
72
72
|
readonly publicationGeneration: number;
|
|
73
73
|
readonly policy:
|
|
74
74
|
| PackageFinalizePolicy
|
|
75
|
-
| ((product:
|
|
75
|
+
| ((product: ScriptablePackBuildProduct) => PackageFinalizePolicy);
|
|
76
76
|
readonly subjectPackageId?: PackageIdType;
|
|
77
77
|
readonly values?: Readonly<Record<string, unknown>>;
|
|
78
78
|
readonly inheritedValues?: Readonly<
|
|
@@ -80,18 +80,20 @@ export interface ParameterizedScriptablePackInput {
|
|
|
80
80
|
>;
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
export interface
|
|
84
|
-
readonly product:
|
|
83
|
+
export interface PreparedScriptablePack {
|
|
84
|
+
readonly product: ScriptablePackBuildProduct;
|
|
85
85
|
readonly finalized: FinalizedPackageTransport;
|
|
86
86
|
readonly facts: ScriptablePackPublicationFacts;
|
|
87
87
|
readonly revision: ResourceRevision;
|
|
88
88
|
readonly publication: AssetPublicationEnvelope;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
export interface
|
|
92
|
-
readonly sources: readonly
|
|
91
|
+
export interface ScriptablePackProductionOptions {
|
|
92
|
+
readonly sources: readonly ScriptablePackInput[];
|
|
93
93
|
readonly declaredExternalOutputs?: readonly ScriptablePackStagedOutput[];
|
|
94
94
|
readonly assetSource?: ScriptablePackAssetSnapshotSource;
|
|
95
|
+
/** Build-time producers used for custom or otherwise uncooked asset rows. */
|
|
96
|
+
readonly cookers?: readonly NativeCooker[];
|
|
95
97
|
readonly availableGuids?: ReadonlySet<string>;
|
|
96
98
|
readonly incomingRefs?: ReadonlyMap<string, readonly string[]>;
|
|
97
99
|
readonly maxPasses?: number;
|
|
@@ -211,7 +213,7 @@ export async function declaredPackExternalOutputs(
|
|
|
211
213
|
}
|
|
212
214
|
if (declaration.format !== 'pack.json') continue;
|
|
213
215
|
if (declaration.value.schemaVersion === '3.0.0') {
|
|
214
|
-
const parsed =
|
|
216
|
+
const parsed = parsePackSourceJson(declaration.value);
|
|
215
217
|
if (!parsed.ok || parsed.value.format !== 'direct') continue;
|
|
216
218
|
const projected = projectDirectPackJson(parsed.value);
|
|
217
219
|
if (!projected.ok) continue;
|
|
@@ -299,6 +301,13 @@ export async function readCookedAuthoredPack(
|
|
|
299
301
|
continue;
|
|
300
302
|
}
|
|
301
303
|
if (isEngineOwnedMaterial(asset)) {
|
|
304
|
+
// Engine-owned material payloads are already cooked, but a legacy Pack
|
|
305
|
+
// source still needs to be projected into the runtime transport route.
|
|
306
|
+
// Mark the package as cooked so prepareLegacyPackTransport stages a
|
|
307
|
+
// published body instead of falling back to the source URL, which the
|
|
308
|
+
// dev route intentionally rejects for cooked v2 inputs.
|
|
309
|
+
hasCookedAsset = true;
|
|
310
|
+
refsByGuid.set(asset.guid.toLowerCase(), [...asset.refs]);
|
|
302
311
|
assets.push({
|
|
303
312
|
guid: asset.guid,
|
|
304
313
|
kind: asset.kind,
|
|
@@ -352,7 +361,7 @@ export interface DirectPackTransport {
|
|
|
352
361
|
readonly packageId: string;
|
|
353
362
|
readonly assets: readonly DirectPackAssetProjection[];
|
|
354
363
|
};
|
|
355
|
-
readonly product:
|
|
364
|
+
readonly product: ScriptablePackBuildProduct;
|
|
356
365
|
readonly finalized: FinalizedPackageTransport;
|
|
357
366
|
readonly facts: ScriptablePackPublicationFacts;
|
|
358
367
|
readonly revision: ResourceRevision;
|
|
@@ -429,9 +438,7 @@ function importedAssetArtifacts(
|
|
|
429
438
|
);
|
|
430
439
|
}
|
|
431
440
|
|
|
432
|
-
function rawDirectProduct(
|
|
433
|
-
input: DirectPackTransportInput,
|
|
434
|
-
): ParameterizedScriptablePackBuildProduct {
|
|
441
|
+
function rawDirectProduct(input: DirectPackTransportInput): ScriptablePackBuildProduct {
|
|
435
442
|
const inputFingerprint = `sha256:${packageTransportRevision({
|
|
436
443
|
packageId: input.projected.packageId,
|
|
437
444
|
sourceRevision: input.sourceRevision,
|
|
@@ -623,7 +630,7 @@ export async function prepareDirectPackTransport(
|
|
|
623
630
|
projectImportProductForBuild(raw.product),
|
|
624
631
|
input.policy,
|
|
625
632
|
);
|
|
626
|
-
const facts =
|
|
633
|
+
const facts = projectScriptablePackPublication(raw);
|
|
627
634
|
if (!facts.ok) return facts;
|
|
628
635
|
const displaySourcePath = input.displaySourcePath ?? input.sourcePath;
|
|
629
636
|
const revision = await scriptablePackResourceRevision(displaySourcePath, raw.inputFingerprint, [
|
|
@@ -654,10 +661,10 @@ export async function prepareDirectPackTransport(
|
|
|
654
661
|
]),
|
|
655
662
|
),
|
|
656
663
|
),
|
|
657
|
-
} as
|
|
664
|
+
} as AnyScriptablePackDefinition;
|
|
658
665
|
const outputs = createStandardAssetOutputProducerRegistry();
|
|
659
666
|
outputs.register(createPreExternalizedSceneAssetOutputProducer());
|
|
660
|
-
const built = await
|
|
667
|
+
const built = await buildScriptablePack({
|
|
661
668
|
definition,
|
|
662
669
|
sourcePath: input.sourcePath,
|
|
663
670
|
outputs,
|
|
@@ -702,7 +709,7 @@ export async function prepareDirectPackTransport(
|
|
|
702
709
|
asset: directAssetForProducer(asset),
|
|
703
710
|
digest: `sha256:${packageTransportRevision({ kind: asset.kind, payload: asset.payload })}`,
|
|
704
711
|
}));
|
|
705
|
-
const product:
|
|
712
|
+
const product: ScriptablePackBuildProduct = {
|
|
706
713
|
...built.value,
|
|
707
714
|
inputFingerprint,
|
|
708
715
|
stagedOutputs,
|
|
@@ -722,7 +729,7 @@ export async function prepareDirectPackTransport(
|
|
|
722
729
|
projectImportProductForBuild(product.product),
|
|
723
730
|
input.policy,
|
|
724
731
|
);
|
|
725
|
-
const facts =
|
|
732
|
+
const facts = projectScriptablePackPublication(product);
|
|
726
733
|
if (!facts.ok) return facts;
|
|
727
734
|
const displaySourcePath = input.displaySourcePath ?? input.sourcePath;
|
|
728
735
|
const revision = await scriptablePackResourceRevision(
|
|
@@ -761,8 +768,8 @@ export async function prepareLegacyPackTransport(
|
|
|
761
768
|
}
|
|
762
769
|
|
|
763
770
|
/** Materialize a dynamic Pack product through the same dev transport seam. */
|
|
764
|
-
export async function
|
|
765
|
-
prepared:
|
|
771
|
+
export async function materializePreparedScriptablePack(
|
|
772
|
+
prepared: PreparedScriptablePack,
|
|
766
773
|
paths: ScriptablePackTransportPaths,
|
|
767
774
|
sink: ScriptablePackTransportSink,
|
|
768
775
|
): Promise<ReadonlyMap<string, string>> {
|
|
@@ -793,8 +800,8 @@ export async function materializePreparedParameterizedScriptablePack(
|
|
|
793
800
|
return receipts;
|
|
794
801
|
}
|
|
795
802
|
|
|
796
|
-
function
|
|
797
|
-
product:
|
|
803
|
+
function projectScriptablePackPublication(
|
|
804
|
+
product: ScriptablePackBuildProduct,
|
|
798
805
|
): Result<ScriptablePackPublicationFacts, ScriptablePackDomainError> {
|
|
799
806
|
const assets = new Map(product.product.assets.map((asset) => [asset.guid.toLowerCase(), asset]));
|
|
800
807
|
const outputs: AssetPublicationOutput[] = [];
|
|
@@ -804,7 +811,7 @@ function projectParameterizedPackPublication(
|
|
|
804
811
|
if (asset === undefined || staged.digest === undefined || staged.sourceKey === undefined) {
|
|
805
812
|
return err({
|
|
806
813
|
code: 'pack-source-output-invalid',
|
|
807
|
-
expected: `
|
|
814
|
+
expected: `ScriptablePack publication output ${guid} to include a product, sourceKey, and digest`,
|
|
808
815
|
hint: 'repair the dynamic Pack output and rebuild the current generation',
|
|
809
816
|
detail: { stage: 'publication', guid },
|
|
810
817
|
});
|
|
@@ -857,7 +864,7 @@ function snapshotSourceForStagedOutputs(
|
|
|
857
864
|
};
|
|
858
865
|
}
|
|
859
866
|
|
|
860
|
-
function
|
|
867
|
+
function composeScriptablePackAssetSource(
|
|
861
868
|
staged: import('./scriptable-pack.js').ScriptablePackAssetSnapshotSource | undefined,
|
|
862
869
|
published: import('./scriptable-pack.js').ScriptablePackAssetSnapshotSource | undefined,
|
|
863
870
|
): import('./scriptable-pack.js').ScriptablePackAssetSnapshotSource | undefined {
|
|
@@ -873,16 +880,16 @@ function composeParameterizedAssetSource(
|
|
|
873
880
|
}
|
|
874
881
|
|
|
875
882
|
/**
|
|
876
|
-
* Build
|
|
883
|
+
* Build ScriptablePack sources in one generation and hand their terminal
|
|
877
884
|
* products to the ordinary Pack v2 finalizer. The worklist is deliberately
|
|
878
885
|
* below publication: it only decides which current-generation products exist.
|
|
879
886
|
*/
|
|
880
|
-
export async function
|
|
881
|
-
options:
|
|
882
|
-
): Promise<Result<ReadonlyMap<string,
|
|
887
|
+
export async function produceScriptablePackProducts(
|
|
888
|
+
options: ScriptablePackProductionOptions,
|
|
889
|
+
): Promise<Result<ReadonlyMap<string, PreparedScriptablePack>, unknown>> {
|
|
883
890
|
if (options.sources.length === 0) return ok(new Map());
|
|
884
891
|
const external = options.declaredExternalOutputs ?? [];
|
|
885
|
-
const assetSource =
|
|
892
|
+
const assetSource = composeScriptablePackAssetSource(
|
|
886
893
|
snapshotSourceForStagedOutputs(external),
|
|
887
894
|
options.assetSource,
|
|
888
895
|
);
|
|
@@ -890,7 +897,7 @@ export async function produceParameterizedScriptablePackProducts(
|
|
|
890
897
|
...(options.availableGuids ?? []),
|
|
891
898
|
...external.map((output) => AssetGuid.format(output.guid).toLowerCase()),
|
|
892
899
|
]);
|
|
893
|
-
const workItems:
|
|
900
|
+
const workItems: ScriptablePackBuildWorkItem[] = options.sources.map((source) => ({
|
|
894
901
|
definition: source.definition,
|
|
895
902
|
sourcePath: source.sourcePath,
|
|
896
903
|
...(source.subjectPackageId === undefined ? {} : { subjectPackageId: source.subjectPackageId }),
|
|
@@ -898,13 +905,14 @@ export async function produceParameterizedScriptablePackProducts(
|
|
|
898
905
|
...(source.inheritedValues === undefined ? {} : { inheritedValues: source.inheritedValues }),
|
|
899
906
|
sourceClosure: source.sourceClosure,
|
|
900
907
|
}));
|
|
901
|
-
const worklist = await
|
|
908
|
+
const worklist = await buildScriptablePackWorklist({
|
|
902
909
|
subjects: workItems,
|
|
903
910
|
outputs: createStandardAssetOutputProducerRegistry(
|
|
904
911
|
options.sources.flatMap((source) =>
|
|
905
912
|
projectScriptablePackSceneComponents(source.definition.sceneComponents),
|
|
906
913
|
),
|
|
907
914
|
),
|
|
915
|
+
...(options.cookers === undefined ? {} : { cookers: options.cookers }),
|
|
908
916
|
...(assetSource === undefined ? {} : { assetSource }),
|
|
909
917
|
availableGuids,
|
|
910
918
|
...(options.incomingRefs === undefined ? {} : { incomingRefs: options.incomingRefs }),
|
|
@@ -917,7 +925,7 @@ export async function produceParameterizedScriptablePackProducts(
|
|
|
917
925
|
.filter((product) => product.product.sourceKey !== undefined)
|
|
918
926
|
.map((product) => [product.product.sourceKey as string, product]),
|
|
919
927
|
);
|
|
920
|
-
const prepared = new Map<string,
|
|
928
|
+
const prepared = new Map<string, PreparedScriptablePack>();
|
|
921
929
|
for (const source of options.sources) {
|
|
922
930
|
const product = productsBySource.get(source.sourcePath);
|
|
923
931
|
if (product === undefined) {
|
|
@@ -933,7 +941,7 @@ export async function produceParameterizedScriptablePackProducts(
|
|
|
933
941
|
projectImportProductForBuild(product.product),
|
|
934
942
|
policy,
|
|
935
943
|
);
|
|
936
|
-
const facts =
|
|
944
|
+
const facts = projectScriptablePackPublication(product);
|
|
937
945
|
if (!facts.ok) return facts;
|
|
938
946
|
const revision = await scriptablePackResourceRevision(
|
|
939
947
|
source.displaySourcePath,
|
package/src/scriptable-pack.ts
CHANGED
|
@@ -136,7 +136,8 @@ export interface ScriptablePackExternalEvidence {
|
|
|
136
136
|
readonly digest?: string;
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
|
|
139
|
+
/** Shared terminal product envelope for every Pack source form. */
|
|
140
|
+
export interface PackBuildProduct {
|
|
140
141
|
readonly product: TerminalImportProduct<unknown>;
|
|
141
142
|
readonly stagedOutputs: readonly ScriptablePackStagedOutput[];
|
|
142
143
|
readonly externalEvidence: readonly ScriptablePackExternalEvidence[];
|