@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.
@@ -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":"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"}
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":"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"}
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.4",
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.4",
31
- "@forgeax/engine-ecs": "0.1.4",
32
- "@forgeax/engine-geometry": "0.1.4",
33
- "@forgeax/engine-pack": "0.1.4",
34
- "@forgeax/engine-scene": "0.1.4",
35
- "@forgeax/engine-types": "0.1.4",
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
+ });
@@ -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',