From 4fd956265fb602ebb47d658fa2c117314064e15e Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Fri, 20 Mar 2026 05:54:44 +0000 Subject: [PATCH] implements PR-30 pack wizard summary snapshot query --- .../FileSystemPackerWorkspaceService.java | 36 ++++++++++++- .../FileSystemPackerWorkspaceServiceTest.java | 53 +++++++++++++++++++ 2 files changed, 88 insertions(+), 1 deletion(-) diff --git a/prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java b/prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java index 8e4bd12c..a717a49d 100644 --- a/prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java +++ b/prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java @@ -9,6 +9,8 @@ import p.packer.PackerWorkspaceService; import p.packer.events.PackerEventKind; import p.packer.events.PackerEventSink; import p.packer.events.PackerProgress; +import p.packer.dtos.PackerPackSummaryAssetDTO; +import p.packer.dtos.PackerPackSummaryDTO; import p.packer.messages.*; import p.packer.messages.assets.*; import p.packer.messages.diagnostics.PackerDiagnosticCategory; @@ -141,7 +143,17 @@ public final class FileSystemPackerWorkspaceService implements PackerWorkspaceSe @Override public PackWorkspaceSummaryResult getPackWorkspaceSummary(PackWorkspaceSummaryRequest request) { - throw new UnsupportedOperationException("pack workspace summary is not implemented yet"); + final PackerProjectContext project = Objects.requireNonNull(request, "request").project(); + final PackerRuntimeSnapshot snapshot = runtimeRegistry.getOrLoad(project).snapshot(); + final List assets = snapshot.assets().stream() + .filter(runtimeAsset -> runtimeAsset.registryEntry().isPresent() && runtimeAsset.registryEntry().get().includedInBuild()) + .sorted(Comparator.comparingInt(runtimeAsset -> runtimeAsset.registryEntry().get().assetId())) + .map(this::toPackSummaryAssetDTO) + .toList(); + return new PackWorkspaceSummaryResult( + PackerOperationStatus.SUCCESS, + "Pack summary resolved from runtime snapshot.", + new PackerPackSummaryDTO(assets.size(), assets)); } @Override @@ -643,6 +655,28 @@ public final class FileSystemPackerWorkspaceService implements PackerWorkspaceSe return PackerWorkspacePaths.relativeAssetRoot(project, assetRoot).replace('\\', '/'); } + private PackerPackSummaryAssetDTO toPackSummaryAssetDTO(PackerRuntimeAsset runtimeAsset) { + final PackerRegistryEntry registryEntry = runtimeAsset.registryEntry() + .orElseThrow(() -> new IllegalArgumentException("pack summary asset must be registered")); + final PackerAssetDeclarationParseResult parsed = runtimeAsset.parsedDeclaration(); + final PackerAssetDeclaration declaration = parsed.declaration(); + final String assetName = declaration != null + ? declaration.name() + : runtimeAsset.assetRoot().getFileName().toString(); + final AssetFamilyCatalog assetFamily = declaration != null + ? declaration.assetFamily() + : AssetFamilyCatalog.UNKNOWN; + final int minArtifactCount = declaration != null ? declaration.artifacts().size() : 0; + final int maxArtifactCount = runtimeAsset.walkProjection().buildCandidateFiles().size(); + return new PackerPackSummaryAssetDTO( + registryEntry.assetId(), + assetName, + assetFamily, + minArtifactCount, + maxArtifactCount, + 0L); + } + private void saveRuntimeCache(PackerProjectContext project, PackerRuntimeSnapshot snapshot) { cacheRepository.save(project, snapshot.cacheState()); } diff --git a/prometeu-packer/prometeu-packer-v1/src/test/java/p/packer/services/FileSystemPackerWorkspaceServiceTest.java b/prometeu-packer/prometeu-packer-v1/src/test/java/p/packer/services/FileSystemPackerWorkspaceServiceTest.java index b7b5e4bf..4131e12a 100644 --- a/prometeu-packer/prometeu-packer-v1/src/test/java/p/packer/services/FileSystemPackerWorkspaceServiceTest.java +++ b/prometeu-packer/prometeu-packer-v1/src/test/java/p/packer/services/FileSystemPackerWorkspaceServiceTest.java @@ -87,6 +87,59 @@ final class FileSystemPackerWorkspaceServiceTest { assertTrue(events.stream().allMatch(event -> event.sequence() >= 0L)); } + @Test + void packSummaryIncludesOnlyRegisteredAssetsIncludedInBuild() throws Exception { + final Path projectRoot = copyFixture("workspaces/read-mixed", tempDir.resolve("pack-summary-mixed")); + final FileSystemPackerWorkspaceService service = service(); + + final var result = service.getPackWorkspaceSummary(new PackWorkspaceSummaryRequest(project(projectRoot))); + + assertEquals(PackerOperationStatus.SUCCESS, result.status()); + assertEquals(1, result.packSummary().totalIncludedAssetCount()); + assertEquals(1, result.packSummary().assets().size()); + assertEquals(1, result.packSummary().assets().getFirst().assetId()); + assertEquals("ui_atlas", result.packSummary().assets().getFirst().assetName()); + } + + @Test + void packSummaryExcludesRegisteredAssetsMarkedOutOfBuild() throws Exception { + final Path projectRoot = copyFixture("workspaces/managed-basic", tempDir.resolve("pack-summary-excluded")); + final Path registryPath = projectRoot.resolve("assets/.prometeu/index.json"); + final ObjectNode registry = (ObjectNode) MAPPER.readTree(registryPath.toFile()); + ((ObjectNode) registry.path("assets").get(0)).put("included_in_build", false); + MAPPER.writerWithDefaultPrettyPrinter().writeValue(registryPath.toFile(), registry); + final FileSystemPackerWorkspaceService service = service(); + + final var result = service.getPackWorkspaceSummary(new PackWorkspaceSummaryRequest(project(projectRoot))); + + assertEquals(PackerOperationStatus.SUCCESS, result.status()); + assertEquals(0, result.packSummary().totalIncludedAssetCount()); + assertTrue(result.packSummary().assets().isEmpty()); + } + + @Test + void packSummaryProjectsMinAndMaxArtifactCounts() throws Exception { + final Path projectRoot = copyFixture("workspaces/managed-basic", tempDir.resolve("pack-summary-artifacts")); + final Path assetRoot = projectRoot.resolve("assets/ui/atlas"); + writeTilePng(assetRoot.resolve("confirm.png"), 16); + writeTilePng(assetRoot.resolve("cancel.png"), 16); + final Path manifestPath = assetRoot.resolve("asset.json"); + final ObjectNode manifest = (ObjectNode) MAPPER.readTree(manifestPath.toFile()); + final var artifacts = manifest.putArray("artifacts"); + artifacts.addObject().put("file", "confirm.png").put("index", 0); + MAPPER.writerWithDefaultPrettyPrinter().writeValue(manifestPath.toFile(), manifest); + final FileSystemPackerWorkspaceService service = service(); + + service.listAssets(new ListAssetsRequest(project(projectRoot), true)); + final var result = service.getPackWorkspaceSummary(new PackWorkspaceSummaryRequest(project(projectRoot))); + + assertEquals(PackerOperationStatus.SUCCESS, result.status()); + assertEquals(1, result.packSummary().assets().size()); + assertEquals(1, result.packSummary().assets().getFirst().minArtifactCount()); + assertEquals(2, result.packSummary().assets().getFirst().maxArtifactCount()); + assertEquals(0L, result.packSummary().assets().getFirst().lastModified()); + } + @Test void createsRegisteredAssetAndWritesManifest() throws Exception { final Path projectRoot = tempDir.resolve("created");