@forgeax/engine-import 0.1.4 → 0.1.7
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/dist/.tsbuildinfo +1 -1
- package/dist/__tests__/scriptable-pack-host.unit.test.d.ts +2 -0
- package/dist/__tests__/scriptable-pack-host.unit.test.d.ts.map +1 -0
- package/dist/__tests__/source-package-publication.integration.test.d.ts +2 -0
- package/dist/__tests__/source-package-publication.integration.test.d.ts.map +1 -0
- package/dist/build-production.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +175 -93
- package/dist/index.mjs.map +1 -1
- package/dist/scriptable-pack-host.d.ts +10 -2
- package/dist/scriptable-pack-host.d.ts.map +1 -1
- package/dist/source-package-publication.d.ts.map +1 -1
- package/package.json +7 -7
- package/src/__tests__/scriptable-pack-host.unit.test.ts +86 -0
- package/src/__tests__/source-package-publication.integration.test.ts +75 -0
- package/src/build-production.ts +6 -0
- package/src/index.ts +1 -0
- package/src/scriptable-pack-host.ts +85 -2
- package/src/source-package-publication.ts +31 -0
|
@@ -3,7 +3,8 @@ import { type NativeCooker } from '@forgeax/engine-pack/native-cooker';
|
|
|
3
3
|
import type { ScanSourceDeclaration } from '@forgeax/engine-pack/scanner';
|
|
4
4
|
import { type ScriptablePackDefinition, type ScriptablePackSourceClosureEntry } from '@forgeax/engine-pack/source';
|
|
5
5
|
import type { AssetGuid as AssetGuidType, AssetPublicationEnvelope, AssetPublicationOutput, ResourceRevision, Result } from '@forgeax/engine-types';
|
|
6
|
-
import type { DdcPack } from './import-runner.js';
|
|
6
|
+
import type { DdcPack, ImportRunnerFs } from './import-runner.js';
|
|
7
|
+
import type { ImporterRegistry } from './importer-registry.js';
|
|
7
8
|
import type { ScriptablePackDomainError, ScriptablePackStagedOutput } from './scriptable-pack.js';
|
|
8
9
|
import { type ScriptableSourcePackageProduct, type ScriptableSourcePackageResult } from './scriptable-source-package.js';
|
|
9
10
|
type FinalizedPackageTransport = Awaited<ReturnType<typeof finalizePackageTransportSource>>;
|
|
@@ -48,12 +49,19 @@ export interface AuthoredPackTransport {
|
|
|
48
49
|
readonly cooked?: CookedAuthoredPack;
|
|
49
50
|
readonly finalized?: FinalizedPackageTransport;
|
|
50
51
|
}
|
|
52
|
+
/** Build-time capabilities required to expose ordinary Meta products to a ScriptablePack. */
|
|
53
|
+
export interface ScriptablePackExternalImportOptions {
|
|
54
|
+
readonly importerRegistry: ImporterRegistry;
|
|
55
|
+
readonly fsForImport: ImportRunnerFs;
|
|
56
|
+
/** Package path aliases from forgeax.assets.paths; defaults to the current project config. */
|
|
57
|
+
readonly assetPaths?: Readonly<Record<string, string>>;
|
|
58
|
+
}
|
|
51
59
|
export declare function canonicalScriptableSourcePath(sourcePath: string): string;
|
|
52
60
|
export declare function scriptablePackInputs(sourcePaths: readonly string[], declarations: ReadonlyMap<string, ScanSourceDeclaration>, cwd: string, generationFor: (displaySourcePath: string) => number, policyFor: (displaySourcePath: string) => ScriptablePackTransportPolicy): ScriptablePackInput[];
|
|
53
61
|
/** Materialize one accepted ScriptablePack without duplicating dev/build loops. */
|
|
54
62
|
export declare function materializePreparedScriptablePack(prepared: PreparedScriptablePack, paths: ScriptablePackTransportPaths, sink: ScriptablePackTransportSink): Promise<ReadonlyMap<string, string>>;
|
|
55
63
|
export declare function readCookedAuthoredPack(authoredPack: AuthoredPackInput, cookers?: readonly NativeCooker[], sourcePath?: string): Promise<CookedAuthoredPack | undefined>;
|
|
56
|
-
export declare function declaredPackExternalOutputs(declarations: ReadonlyMap<string, ScanSourceDeclaration>, cookers?: readonly NativeCooker[], requiredGuids?: readonly AssetGuidType[]): Promise<readonly ScriptablePackStagedOutput[]>;
|
|
64
|
+
export declare function declaredPackExternalOutputs(declarations: ReadonlyMap<string, ScanSourceDeclaration>, cookers?: readonly NativeCooker[], requiredGuids?: readonly AssetGuidType[], externalImport?: ScriptablePackExternalImportOptions): Promise<readonly ScriptablePackStagedOutput[]>;
|
|
57
65
|
/** Normalize one authored Pack and, when needed, run its registered cooker once. */
|
|
58
66
|
export declare function prepareAuthoredPackTransport(authoredPack: AuthoredPackInput, cookers: readonly NativeCooker[] | undefined, policyFor: (guid: string) => PackageFinalizePolicy, sourcePath?: string): Promise<AuthoredPackTransport>;
|
|
59
67
|
/** Project one produced ScriptablePack into the publication tuple shared by dev and build. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scriptable-pack-host.d.ts","sourceRoot":"","sources":["../src/scriptable-pack-host.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,KAAK,iBAAiB,EACtB,8BAA8B,
|
|
1
|
+
{"version":3,"file":"scriptable-pack-host.d.ts","sourceRoot":"","sources":["../src/scriptable-pack-host.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"source-package-publication.d.ts","sourceRoot":"","sources":["../src/source-package-publication.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,2BAA2B,EAChC,oBAAoB,EACpB,KAAK,OAAO,EAGb,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,KAAK,YAAY,EAGjB,KAAK,gBAAgB,EAEtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAE/B,MAAM,4BAA4B,CAAC;AAQpC,UAAU,sBAAuB,SAAQ,2BAA2B;IAClE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,yBAAyB,CAAC;CAC7C;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,eAAe,EAAE,SAAS,YAAY,EAAE,CAAC;IAClD,QAAQ,CAAC,WAAW,EAAE,SAAS,YAAY,EAAE,CAAC;IAC9C,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,QAAQ,CAAC,SAAS,CAAC,EAAE;QACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;KACvB,CAAC;CACH;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC1C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAC;CACzC;AAED,MAAM,MAAM,uBAAuB,GAC/B;IACE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;IAC1C,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IACpC,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAC;CACtC,GACD;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,sBAAsB,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAE3F,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,KAAK,EAAE,sBAAsB,CAAC;IACvC,QAAQ,CAAC,GAAG,EAAE,sBAAsB,CAAC;IACrC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;IAC1C,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;CACrC;AAED,MAAM,MAAM,6BAA6B,GACrC;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,uBAAuB,CAAA;CAAE,GAClE;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,sBAAsB,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"source-package-publication.d.ts","sourceRoot":"","sources":["../src/source-package-publication.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forgeax/engine-import",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -27,12 +27,12 @@
|
|
|
27
27
|
"LICENSE"
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@forgeax/engine-ddc": "0.1.
|
|
31
|
-
"@forgeax/engine-ecs": "0.1.
|
|
32
|
-
"@forgeax/engine-geometry": "0.1.
|
|
33
|
-
"@forgeax/engine-pack": "0.1.
|
|
34
|
-
"@forgeax/engine-scene": "0.1.
|
|
35
|
-
"@forgeax/engine-types": "0.1.
|
|
30
|
+
"@forgeax/engine-ddc": "0.1.7",
|
|
31
|
+
"@forgeax/engine-ecs": "0.1.7",
|
|
32
|
+
"@forgeax/engine-geometry": "0.1.7",
|
|
33
|
+
"@forgeax/engine-pack": "0.1.7",
|
|
34
|
+
"@forgeax/engine-scene": "0.1.7",
|
|
35
|
+
"@forgeax/engine-types": "0.1.7",
|
|
36
36
|
"@noble/hashes": "^2.2.0"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { AssetGuid } from '@forgeax/engine-pack/guid';
|
|
2
|
+
import type { ScanSourceDeclaration } from '@forgeax/engine-pack/scanner';
|
|
3
|
+
import type {
|
|
4
|
+
Asset,
|
|
5
|
+
AssetGuid as AssetGuidType,
|
|
6
|
+
ImportContext,
|
|
7
|
+
Importer,
|
|
8
|
+
} from '@forgeax/engine-types';
|
|
9
|
+
import { describe, expect, it } from 'vitest';
|
|
10
|
+
import { ImporterRegistry } from '../importer-registry.js';
|
|
11
|
+
import { declaredPackExternalOutputs } from '../scriptable-pack-host.js';
|
|
12
|
+
|
|
13
|
+
const GUID = '019ffa97-0000-7000-8000-000000000001';
|
|
14
|
+
|
|
15
|
+
function parseGuid(value: string): AssetGuidType {
|
|
16
|
+
const parsed = AssetGuid.parse(value);
|
|
17
|
+
if (!parsed.ok) throw parsed.error;
|
|
18
|
+
return parsed.value;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
describe('ScriptablePack external Meta staging', () => {
|
|
22
|
+
it('imports ordinary Meta dependencies into the current staged generation', async () => {
|
|
23
|
+
const importer: Importer = {
|
|
24
|
+
key: 'fixture',
|
|
25
|
+
import: async (ctx: ImportContext) => ({
|
|
26
|
+
ok: true,
|
|
27
|
+
value: {
|
|
28
|
+
assets: [
|
|
29
|
+
{
|
|
30
|
+
guid: ctx.subAssets[0]?.guid ?? GUID,
|
|
31
|
+
kind: 'mesh',
|
|
32
|
+
payload: {
|
|
33
|
+
kind: 'mesh',
|
|
34
|
+
vertices: new Float32Array([0, 1, 2]),
|
|
35
|
+
attributes: {},
|
|
36
|
+
submeshes: [],
|
|
37
|
+
materialSlots: [],
|
|
38
|
+
} satisfies Asset,
|
|
39
|
+
refs: [],
|
|
40
|
+
artifacts: {},
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
sourceDependencies: [],
|
|
44
|
+
},
|
|
45
|
+
}),
|
|
46
|
+
};
|
|
47
|
+
const registry = new ImporterRegistry();
|
|
48
|
+
registry.register(importer);
|
|
49
|
+
const declaration = {
|
|
50
|
+
format: 'meta.json',
|
|
51
|
+
sourcePath: '/project/assets/model.bin.meta.json',
|
|
52
|
+
sourceRevision: 'sha256:meta',
|
|
53
|
+
value: {
|
|
54
|
+
schemaVersion: '1.0.0',
|
|
55
|
+
kind: 'external-asset-package',
|
|
56
|
+
importer: 'fixture',
|
|
57
|
+
source: 'model.bin',
|
|
58
|
+
importSettings: {},
|
|
59
|
+
subAssets: [{ guid: GUID, sourceIndex: 0, kind: 'mesh' }],
|
|
60
|
+
},
|
|
61
|
+
} satisfies Extract<ScanSourceDeclaration, { readonly format: 'meta.json' }>;
|
|
62
|
+
|
|
63
|
+
const outputs = await declaredPackExternalOutputs(
|
|
64
|
+
new Map([[declaration.sourcePath, declaration]]),
|
|
65
|
+
[],
|
|
66
|
+
[parseGuid(GUID)],
|
|
67
|
+
{
|
|
68
|
+
importerRegistry: registry,
|
|
69
|
+
fsForImport: {
|
|
70
|
+
readSource: async () => ({ ok: true as const, value: new Uint8Array([1, 2, 3]) }),
|
|
71
|
+
},
|
|
72
|
+
assetPaths: {},
|
|
73
|
+
},
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
expect(outputs).toHaveLength(1);
|
|
77
|
+
const output = outputs[0];
|
|
78
|
+
expect(output).toBeDefined();
|
|
79
|
+
if (output === undefined) return;
|
|
80
|
+
expect(AssetGuid.format(output.guid)).toBe(GUID);
|
|
81
|
+
expect(output.asset).toMatchObject({ kind: 'mesh' });
|
|
82
|
+
expect(Array.from((output.asset as Asset & { vertices: Float32Array }).vertices)).toEqual([
|
|
83
|
+
0, 1, 2,
|
|
84
|
+
]);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { mkdtemp, rm } from 'node:fs/promises';
|
|
2
|
+
import { tmpdir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { afterEach, describe, expect, it } from 'vitest';
|
|
5
|
+
import {
|
|
6
|
+
commitImportPublication,
|
|
7
|
+
discardImportPublication,
|
|
8
|
+
type ImportPublicationInput,
|
|
9
|
+
stageImportPublication,
|
|
10
|
+
} from '../source-package-publication.js';
|
|
11
|
+
|
|
12
|
+
const GUID = '019e3969-1d48-7c3b-ac24-6d68f457065f';
|
|
13
|
+
const KEY = 'a'.repeat(64);
|
|
14
|
+
|
|
15
|
+
function input(root: string, desiredKey = KEY): ImportPublicationInput {
|
|
16
|
+
return {
|
|
17
|
+
root,
|
|
18
|
+
guid: GUID,
|
|
19
|
+
desiredKey,
|
|
20
|
+
pack: {
|
|
21
|
+
schemaVersion: '2.0.0',
|
|
22
|
+
assets: [{ guid: GUID, kind: 'fixture', payload: { value: 'same' }, refs: [] }],
|
|
23
|
+
},
|
|
24
|
+
previousCatalog: [],
|
|
25
|
+
nextCatalog: [],
|
|
26
|
+
publishedGuids: [GUID],
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
describe('source package publication concurrency', () => {
|
|
31
|
+
const roots: string[] = [];
|
|
32
|
+
|
|
33
|
+
afterEach(async () => {
|
|
34
|
+
await Promise.all(roots.splice(0).map((root) => rm(root, { recursive: true, force: true })));
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('waits for an equivalent newer owner after a strict stale commit', async () => {
|
|
38
|
+
const root = await mkdtemp(join(tmpdir(), 'forgeax-source-publication-'));
|
|
39
|
+
roots.push(root);
|
|
40
|
+
const publicationInput = input(root);
|
|
41
|
+
const first = await stageImportPublication(publicationInput);
|
|
42
|
+
const second = await stageImportPublication(publicationInput);
|
|
43
|
+
expect(first.ok).toBe(true);
|
|
44
|
+
expect(second.ok).toBe(true);
|
|
45
|
+
if (!first.ok || !second.ok) return;
|
|
46
|
+
|
|
47
|
+
const winner = (async () => {
|
|
48
|
+
await new Promise((resolve) => setTimeout(resolve, 40));
|
|
49
|
+
return commitImportPublication(second.candidate);
|
|
50
|
+
})();
|
|
51
|
+
const loser = await commitImportPublication(first.candidate);
|
|
52
|
+
const winnerResult = await winner;
|
|
53
|
+
|
|
54
|
+
expect(loser).toMatchObject({ ok: true, head: { state: 'current', currentKey: KEY } });
|
|
55
|
+
expect(winnerResult).toMatchObject({ ok: true, head: { state: 'current', currentKey: KEY } });
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('keeps a stale publication with a different desired key fail-closed', async () => {
|
|
59
|
+
const root = await mkdtemp(join(tmpdir(), 'forgeax-source-publication-'));
|
|
60
|
+
roots.push(root);
|
|
61
|
+
const first = await stageImportPublication(input(root, 'a'.repeat(64)));
|
|
62
|
+
const second = await stageImportPublication(input(root, 'b'.repeat(64)));
|
|
63
|
+
expect(first.ok).toBe(true);
|
|
64
|
+
expect(second.ok).toBe(true);
|
|
65
|
+
if (!first.ok || !second.ok) return;
|
|
66
|
+
|
|
67
|
+
const result = await commitImportPublication(first.candidate);
|
|
68
|
+
await discardImportPublication(second.candidate);
|
|
69
|
+
|
|
70
|
+
expect(result).toMatchObject({
|
|
71
|
+
ok: false,
|
|
72
|
+
error: { code: 'source-package-ddc-failed', detail: 'DDC lifecycle commit returned stale' },
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
});
|
package/src/build-production.ts
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
type CatalogBuildResult,
|
|
4
4
|
createRuntimePackPublication,
|
|
5
5
|
finalizePackageTransportSource,
|
|
6
|
+
loadAssetConfig,
|
|
6
7
|
metaPathForGuid,
|
|
7
8
|
projectCookedPackageEntry,
|
|
8
9
|
} from '@forgeax/engine-pack/build';
|
|
@@ -130,6 +131,11 @@ async function buildAuthoredPackages(
|
|
|
130
131
|
context.inventory.sourceDeclarations,
|
|
131
132
|
context.cookers,
|
|
132
133
|
inputs.flatMap((input) => Object.values(input.definition.externalAssets)),
|
|
134
|
+
{
|
|
135
|
+
importerRegistry: context.importerRegistry,
|
|
136
|
+
fsForImport: context.fsForImport,
|
|
137
|
+
assetPaths: loadAssetConfig(context.cwd).paths,
|
|
138
|
+
},
|
|
133
139
|
),
|
|
134
140
|
);
|
|
135
141
|
if (!preparedResult.ok) throw context.fail(preparedResult.error);
|
package/src/index.ts
CHANGED
|
@@ -113,6 +113,7 @@ export {
|
|
|
113
113
|
produceScriptablePackProducts,
|
|
114
114
|
projectScriptablePackPublication,
|
|
115
115
|
readCookedAuthoredPack,
|
|
116
|
+
type ScriptablePackExternalImportOptions,
|
|
116
117
|
type ScriptablePackInput,
|
|
117
118
|
type ScriptablePackPublicationFacts,
|
|
118
119
|
type ScriptablePackTransportPaths,
|
|
@@ -5,7 +5,9 @@ import { createAcceptedPublication } from '@forgeax/engine-ddc';
|
|
|
5
5
|
import {
|
|
6
6
|
type AuthoredPackInput,
|
|
7
7
|
finalizePackageTransportSource,
|
|
8
|
+
loadAssetConfig,
|
|
8
9
|
type PackageFinalizePolicy,
|
|
10
|
+
resolveAssetSource,
|
|
9
11
|
upgradeLegacyAuthoredPack,
|
|
10
12
|
} from '@forgeax/engine-pack/build';
|
|
11
13
|
import { AssetGuid } from '@forgeax/engine-pack/guid';
|
|
@@ -25,8 +27,9 @@ import type {
|
|
|
25
27
|
ResourceRevision,
|
|
26
28
|
Result,
|
|
27
29
|
} from '@forgeax/engine-types';
|
|
28
|
-
import { err, ok } from '@forgeax/engine-types';
|
|
29
|
-
import type { DdcPack } from './import-runner.js';
|
|
30
|
+
import { AssetError, err, ok } from '@forgeax/engine-types';
|
|
31
|
+
import type { DdcPack, ImportRunnerFs, RunImportMeta } from './import-runner.js';
|
|
32
|
+
import type { ImporterRegistry } from './importer-registry.js';
|
|
30
33
|
import { projectImportProductForBuild } from './pack-projection.js';
|
|
31
34
|
import type { ScriptablePackDomainError, ScriptablePackStagedOutput } from './scriptable-pack.js';
|
|
32
35
|
import { createStandardAssetOutputProducerRegistry } from './scriptable-pack-output-producers.js';
|
|
@@ -39,6 +42,7 @@ import {
|
|
|
39
42
|
type ScriptableSourcePackageProduct,
|
|
40
43
|
type ScriptableSourcePackageResult,
|
|
41
44
|
} from './scriptable-source-package.js';
|
|
45
|
+
import { produceSourcePackage } from './source-package.js';
|
|
42
46
|
|
|
43
47
|
type FinalizedPackageTransport = Awaited<ReturnType<typeof finalizePackageTransportSource>>;
|
|
44
48
|
|
|
@@ -95,6 +99,14 @@ export interface AuthoredPackTransport {
|
|
|
95
99
|
readonly finalized?: FinalizedPackageTransport;
|
|
96
100
|
}
|
|
97
101
|
|
|
102
|
+
/** Build-time capabilities required to expose ordinary Meta products to a ScriptablePack. */
|
|
103
|
+
export interface ScriptablePackExternalImportOptions {
|
|
104
|
+
readonly importerRegistry: ImporterRegistry;
|
|
105
|
+
readonly fsForImport: ImportRunnerFs;
|
|
106
|
+
/** Package path aliases from forgeax.assets.paths; defaults to the current project config. */
|
|
107
|
+
readonly assetPaths?: Readonly<Record<string, string>>;
|
|
108
|
+
}
|
|
109
|
+
|
|
98
110
|
export function canonicalScriptableSourcePath(sourcePath: string): string {
|
|
99
111
|
const normalized = sourcePath.replaceAll('\\', '/');
|
|
100
112
|
const marker = '/assets/';
|
|
@@ -223,11 +235,82 @@ export async function declaredPackExternalOutputs(
|
|
|
223
235
|
declarations: ReadonlyMap<string, ScanSourceDeclaration>,
|
|
224
236
|
cookers: readonly NativeCooker[] = [],
|
|
225
237
|
requiredGuids: readonly AssetGuidType[] = [],
|
|
238
|
+
externalImport?: ScriptablePackExternalImportOptions,
|
|
226
239
|
): Promise<readonly ScriptablePackStagedOutput[]> {
|
|
227
240
|
if (requiredGuids.length === 0) return [];
|
|
228
241
|
const required = new Set(requiredGuids.map((guid) => AssetGuid.format(guid).toLowerCase()));
|
|
229
242
|
const outputs: ScriptablePackStagedOutput[] = [];
|
|
230
243
|
for (const declaration of declarations.values()) {
|
|
244
|
+
if (declaration.format === 'meta.json') {
|
|
245
|
+
if (externalImport === undefined) continue;
|
|
246
|
+
if (!declaration.value.subAssets.some((asset) => required.has(asset.guid.toLowerCase()))) {
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
const assetPaths = externalImport.assetPaths ?? loadAssetConfig(process.cwd()).paths;
|
|
250
|
+
const resolved = resolveAssetSource(
|
|
251
|
+
declaration.sourcePath,
|
|
252
|
+
declaration.value.source,
|
|
253
|
+
assetPaths,
|
|
254
|
+
);
|
|
255
|
+
if (!resolved.ok) {
|
|
256
|
+
throw new AssetError({
|
|
257
|
+
code: 'asset-not-imported',
|
|
258
|
+
expected: `a resolvable source for Meta dependency ${declaration.sourcePath}`,
|
|
259
|
+
hint: 'repair the Meta source path before rebuilding the ScriptablePack',
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
const meta: RunImportMeta = {
|
|
263
|
+
importer: declaration.value.importer,
|
|
264
|
+
source: resolved.value,
|
|
265
|
+
sourceRevision: declaration.sourceRevision,
|
|
266
|
+
...(declaration.value.packageId === undefined
|
|
267
|
+
? {}
|
|
268
|
+
: { packageId: declaration.value.packageId }),
|
|
269
|
+
...(declaration.value.provenance === undefined
|
|
270
|
+
? {}
|
|
271
|
+
: { provenance: declaration.value.provenance }),
|
|
272
|
+
...(declaration.value.revision === undefined
|
|
273
|
+
? {}
|
|
274
|
+
: { revision: declaration.value.revision }),
|
|
275
|
+
...(declaration.value.diagnostics === undefined
|
|
276
|
+
? {}
|
|
277
|
+
: { diagnostics: declaration.value.diagnostics }),
|
|
278
|
+
importSettings: declaration.value.importSettings,
|
|
279
|
+
...(declaration.value.sourceOverrides === undefined
|
|
280
|
+
? {}
|
|
281
|
+
: { sourceOverrides: declaration.value.sourceOverrides }),
|
|
282
|
+
subAssets: declaration.value.subAssets.map(({ guid, sourceIndex, sourceKey, kind }) => ({
|
|
283
|
+
guid,
|
|
284
|
+
sourceIndex,
|
|
285
|
+
...(sourceKey === undefined ? {} : { sourceKey }),
|
|
286
|
+
kind,
|
|
287
|
+
})),
|
|
288
|
+
buildPack: false,
|
|
289
|
+
};
|
|
290
|
+
const sourcePackage = await produceSourcePackage({
|
|
291
|
+
meta,
|
|
292
|
+
registry: externalImport.importerRegistry,
|
|
293
|
+
fs: externalImport.fsForImport,
|
|
294
|
+
});
|
|
295
|
+
if (!sourcePackage.ok) {
|
|
296
|
+
throw new AssetError({
|
|
297
|
+
code: 'asset-not-imported',
|
|
298
|
+
expected: `the ${declaration.value.importer} importer to produce Meta dependency outputs`,
|
|
299
|
+
hint: `repair ${declaration.sourcePath} before rebuilding the ScriptablePack`,
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
for (const asset of sourcePackage.value.product.assets) {
|
|
303
|
+
const key = asset.guid.toLowerCase();
|
|
304
|
+
if (!required.has(key)) continue;
|
|
305
|
+
const parsed = AssetGuid.parse(asset.guid);
|
|
306
|
+
if (!parsed.ok) throw parsed.error;
|
|
307
|
+
outputs.push({
|
|
308
|
+
guid: parsed.value,
|
|
309
|
+
asset: { kind: asset.kind, ...(asset.payload as Record<string, unknown>) } as Asset,
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
231
314
|
if (declaration.format !== 'pack.json') continue;
|
|
232
315
|
const declaredAssets = declaration.value.assets.filter((asset) =>
|
|
233
316
|
required.has(asset.guid.toLowerCase()),
|
|
@@ -83,6 +83,33 @@ function inspectHead(root: string, guid: string, desiredKey: string): Promise<Dd
|
|
|
83
83
|
return new DdcLifecycle(root).inspect(guid, desiredKey);
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
const PUBLICATION_SETTLE_TIMEOUT_MS = 5_000;
|
|
87
|
+
const PUBLICATION_SETTLE_POLL_MS = 10;
|
|
88
|
+
|
|
89
|
+
async function inspectAfterSupersededCommit(candidate: StagedSourcePackageDdc): Promise<DdcHead> {
|
|
90
|
+
let head = await inspectHead(candidate.root, candidate.lease.guid, candidate.lease.desiredKey);
|
|
91
|
+
if (head.state === 'current' && head.currentKey === candidate.lease.desiredKey) return head;
|
|
92
|
+
|
|
93
|
+
// A newer owner may already have superseded this lease while it is still
|
|
94
|
+
// cooking. The strict DDC CAS correctly returns `stale` to this candidate;
|
|
95
|
+
// wait for that owner to publish before turning an equivalent publication
|
|
96
|
+
// into a user-visible import failure. The wait is bounded so a crashed
|
|
97
|
+
// owner never leaves the caller hanging and a different desired key still
|
|
98
|
+
// fails closed.
|
|
99
|
+
const deadline = Date.now() + PUBLICATION_SETTLE_TIMEOUT_MS;
|
|
100
|
+
while (
|
|
101
|
+
Date.now() < deadline &&
|
|
102
|
+
head.activeLease !== undefined &&
|
|
103
|
+
head.activeLease.attempt !== candidate.lease.attempt &&
|
|
104
|
+
head.activeLease.desiredKey === candidate.lease.desiredKey
|
|
105
|
+
) {
|
|
106
|
+
await new Promise((resolve) => setTimeout(resolve, PUBLICATION_SETTLE_POLL_MS));
|
|
107
|
+
head = await inspectHead(candidate.root, candidate.lease.guid, candidate.lease.desiredKey);
|
|
108
|
+
if (head.state === 'current' && head.currentKey === candidate.lease.desiredKey) return head;
|
|
109
|
+
}
|
|
110
|
+
return head;
|
|
111
|
+
}
|
|
112
|
+
|
|
86
113
|
async function stageSourcePackageDdc(
|
|
87
114
|
input: SourcePackageDdcEntryInput,
|
|
88
115
|
): Promise<Result<StagedSourcePackageDdc, SourcePackageError>> {
|
|
@@ -106,6 +133,10 @@ async function commitSourcePackageDdc(
|
|
|
106
133
|
try {
|
|
107
134
|
const commit = await candidate.session.commitEntry(candidate, candidate.lease.desiredKey);
|
|
108
135
|
if (commit.result !== 'current') {
|
|
136
|
+
const head = await inspectAfterSupersededCommit(candidate);
|
|
137
|
+
if (head.state === 'current' && head.currentKey === candidate.lease.desiredKey) {
|
|
138
|
+
return ok(head);
|
|
139
|
+
}
|
|
109
140
|
return err(
|
|
110
141
|
sourcePackageError('source-package-ddc-failed', candidate.context, {
|
|
111
142
|
stage: 'ddc',
|