@forgeax/engine-pack 0.1.32 → 0.1.33

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forgeax/engine-pack",
3
- "version": "0.1.32",
3
+ "version": "0.1.33",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -128,7 +128,7 @@
128
128
  }
129
129
  },
130
130
  "dependencies": {
131
- "@forgeax/engine-types": "0.1.32",
131
+ "@forgeax/engine-types": "0.1.33",
132
132
  "@noble/hashes": "^2.2.0",
133
133
  "fast-glob": "^3.3.3",
134
134
  "typescript": "^5.8.3",
@@ -1,4 +1,4 @@
1
- import { mkdtemp, readFile, rm } from 'node:fs/promises';
1
+ import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
2
2
  import { tmpdir } from 'node:os';
3
3
  import { join } from 'node:path';
4
4
  import { afterEach, describe, expect, it } from 'vitest';
@@ -296,3 +296,73 @@ describe('Pack authoring gateway', () => {
296
296
  expect(verified).toMatchObject({ ok: true, value: { summary: { assetCount: 1 } } });
297
297
  });
298
298
  });
299
+
300
+ it('inspects the exact source revision used by rebuild conflict checks', async () => {
301
+ const root = await mkdtemp(join(tmpdir(), 'forgeax-inspect-revision-'));
302
+ roots.push(root);
303
+ const outputs = [
304
+ {
305
+ packageId: SOURCE_PACKAGE,
306
+ sourceKey: 'mesh/main',
307
+ guid: AssetGuid.format(AssetGuid.derive(packageId(SOURCE_PACKAGE), 'mesh/main')),
308
+ kind: 'mesh',
309
+ sourcePath: 'assets/source.pack.ts',
310
+ ready: true,
311
+ },
312
+ ];
313
+ let published = false;
314
+ const gateway = createFileSystemPackAuthoringGateway({
315
+ gameRoot: root,
316
+ materialized: () => (published ? outputs : []),
317
+ rebuild: async () => ({ ok: true, value: undefined }),
318
+ });
319
+ const created = await gateway.execute({
320
+ operation: 'asset-source.create',
321
+ requestId: 'create',
322
+ targetPath: 'assets/source.pack.ts',
323
+ format: 'pack.ts',
324
+ packageId: SOURCE_PACKAGE,
325
+ });
326
+ expect(created.ok).toBe(true);
327
+ if (!created.ok) return;
328
+ published = true;
329
+ const inspected = await gateway.execute({
330
+ operation: 'asset.inspect',
331
+ subject: 'assets/source.pack.ts',
332
+ requestId: 'inspect',
333
+ });
334
+ expect(inspected).toMatchObject({
335
+ ok: true,
336
+ value: {
337
+ revision: created.value.revision,
338
+ sourcePath: 'assets/source.pack.ts',
339
+ assets: outputs,
340
+ },
341
+ });
342
+ const rebuilt = await gateway.execute({
343
+ operation: 'asset-source.rebuild',
344
+ sourcePath: 'assets/source.pack.ts',
345
+ expectedRevision: created.value.revision,
346
+ requestId: 'rebuild',
347
+ });
348
+ expect(rebuilt).toMatchObject({
349
+ ok: true,
350
+ value: { assets: outputs, revision: created.value.revision },
351
+ });
352
+ const path = join(root, 'assets/source.pack.ts');
353
+ await writeFile(path, `${await readFile(path, 'utf8')}\n// source edit\n`);
354
+ const changed = await gateway.execute({
355
+ operation: 'asset.inspect',
356
+ subject: 'assets/source.pack.ts',
357
+ requestId: 'inspect-edited',
358
+ });
359
+ expect(changed.ok).toBe(true);
360
+ if (changed.ok) expect(changed.value.revision).not.toBe(created.value.revision);
361
+ const stale = await gateway.execute({
362
+ operation: 'asset-source.rebuild',
363
+ sourcePath: 'assets/source.pack.ts',
364
+ expectedRevision: created.value.revision,
365
+ requestId: 'stale',
366
+ });
367
+ expect(stale).toMatchObject({ ok: false, error: { code: 'pack-source-revision-conflict' } });
368
+ });
@@ -817,6 +817,19 @@ async function inspectAsset(
817
817
  const selected = subjectFor(gameRoot, snapshot, operation);
818
818
  if (!selected.ok) return selected;
819
819
  const subject = selected.value;
820
+ const source = await readConfined({ gameRoot }, operation, subject.relativePath);
821
+ if (!source.ok) return source;
822
+ const inspectedSource = {
823
+ ...sourceResult(subject, operation),
824
+ revision: source.value.revision,
825
+ ...(subject.format === 'source'
826
+ ? {
827
+ assets: snapshot.materialized
828
+ .filter((asset) => asset.packageId === packageKey(subject.packageId))
829
+ .map((asset) => ({ ...asset })),
830
+ }
831
+ : {}),
832
+ };
820
833
  if (operation.sourceKey !== undefined) {
821
834
  if (!isValidPackSourceKey(operation.sourceKey)) {
822
835
  return err(
@@ -851,7 +864,7 @@ async function inspectAsset(
851
864
  candidate.sourceKey === operation.sourceKey,
852
865
  );
853
866
  return ok({
854
- ...sourceResult(subject, operation),
867
+ ...inspectedSource,
855
868
  sourceKey: asset.sourceKey,
856
869
  guid: asset.guid,
857
870
  kind: asset.kind,
@@ -871,7 +884,7 @@ async function inspectAsset(
871
884
  candidate.sourceKey === operation.sourceKey,
872
885
  );
873
886
  return ok({
874
- ...sourceResult(subject, operation),
887
+ ...inspectedSource,
875
888
  sourceKey: operation.sourceKey,
876
889
  guid,
877
890
  ...(materialized === undefined
@@ -897,7 +910,7 @@ async function inspectAsset(
897
910
  const resolved = await resolveInstance(snapshot, subject);
898
911
  if (!resolved.ok) return resolved;
899
912
  return ok({
900
- ...sourceResult(subject, operation),
913
+ ...inspectedSource,
901
914
  parameters: resolved.value.parameters.map((parameter) => ({
902
915
  name: parameter.name,
903
916
  type: parameter.type,
@@ -911,7 +924,7 @@ async function inspectAsset(
911
924
  parentChain: resolved.value.parentChain,
912
925
  });
913
926
  }
914
- return ok(sourceResult(subject, operation));
927
+ return ok(inspectedSource);
915
928
  }
916
929
 
917
930
  function listAssets(
@@ -2188,6 +2201,9 @@ async function executeRaw(
2188
2201
  selected.value.packageId,
2189
2202
  {
2190
2203
  format: refreshed.value.relative.endsWith('.pack.json') ? 'pack.json' : 'pack.ts',
2204
+ assets: refreshedSnapshot.value.materialized
2205
+ .filter((asset) => asset.packageId === packageKey(selected.value.packageId))
2206
+ .map((asset) => ({ ...asset })),
2191
2207
  },
2192
2208
  );
2193
2209
  }