Skip to content

fix(packages): await metadataPayloadBuilder.build() in CreatePackageUseCase#1050

Open
ifoche wants to merge 7 commits into
developmentfrom
fix/empty-module-package-contents
Open

fix(packages): await metadataPayloadBuilder.build() in CreatePackageUseCase#1050
ifoche wants to merge 7 commits into
developmentfrom
fix/empty-module-package-contents

Conversation

@ifoche

@ifoche ifoche commented Mar 4, 2026

Copy link
Copy Markdown
Member

Summary

  • Fix missing await on metadataPayloadBuilder.build() in CreatePackageUseCase, which caused a raw Promise to be stored as package contents instead of the resolved metadata payload — making all module-generated packages appear empty
  • Remove unnecessary generic type parameters from TransformationRepository.mapPackageTo/mapPackageFrom to prevent Promise objects from being silently accepted as payload (compile-time safety)
  • Add unit tests for CreatePackageUseCase (5 test cases)

Related Tasks

Test plan

  • Run yarn test — all 393 tests pass (48 files)
  • Run yarn build core-app — builds cleanly
  • Manual: create a module with a dataset, generate a package, verify the package contains the dataset metadata
  • Manual: import the generated package on another instance, verify elements appear in the result summary
  • Manual: download package as JSON, verify metadata objects are present
  • Manual: compare package with local instance, verify diff shows actual differences

🤖 Generated with Claude Code

ifoche and others added 2 commits March 4, 2026 13:01
…seCase

The async build() call was missing `await`, causing a raw Promise object
to be stored as package contents instead of the resolved MetadataPackage.
This made all module-generated packages appear empty (0 elements on import,
empty JSON downloads, no diff data, empty mapping tab).

Also removes unnecessary generic type parameters from TransformationRepository
to prevent Promise objects from being silently accepted as payload, and adds
unit tests for CreatePackageUseCase.

Closes: https://app.clickup.com/t/869bvjxj9

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Include the OpenSpec proposal, design, specs, and tasks for the
fix-empty-module-package-contents change. Add .claude/ to .gitignore.
Also includes prettier formatting applied by pre-commit hook.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@bundlemon

bundlemon Bot commented Mar 4, 2026

Copy link
Copy Markdown

BundleMon

No change in files bundle size

Groups updated (1)
Status Path Size Limits
Build Folder
./**/*
2.67MB (+43B 0%) +20%

Final result: ✅

View report in BundleMon website ➡️


Current branch size history | Target branch size history

xurxodev added 3 commits June 24, 2026 08:24
…le-package-contents

# Conflicts:
#	src/data/tracked-entity-instances/TEID2ApiRepository.ts
…onstructor param

Merging development added a userRepository constructor parameter to
CreatePackageUseCase, shifting localInstance to the 5th position. The
test suite still instantiated the use case with the old 4-arg
signature, leaving localInstance undefined and breaking all 5 tests.

@xurxodev xurxodev left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks @ifoche

This PR fixes a real bug: a missing await on metadataPayloadBuilder.build() in CreatePackageUseCase was storing an unresolved Promise as package contents, makinage empty. The fix itself is correct andminimal. The branch originally also narrowed TransformationRepository.mapPackageTo/mapPackageFrom from generic to a fiMetadataPackage type as an extra safety net a — that part has since been reverted on this branch back to development's fully generic signature, because it broke other legitimate callers once merged with development (see below). What's left to fix ile.

  1. Should fix - src/domain/packages/usecases/tests/Creat doubles don't follow the project'sestablished pattern. The rest of the codebase builds test doubles with ts-mockito (mock/when/instance) plus givenA... helper functions that keep construction out osrc/domain/metadata/builders/tests/MetadataPayloadBuilder.spec.tsx, e.g. givenMetadataPayloadBuilderOfCategory). Tnew spec instead hand-rolls every dependency lt inline in beforeEach, and reimplementsStorageClient/DynamicRepositoryFactory collaborators by hand instead of using mock(...)/instance(...). Worth aligning with the existing convention for consistency ng out of sync with how the rest of the suitemocks the same collaborators (DynamicRepositoryFactory, UserRepository, TransformationRepository).

  2. Recommendations non blocking

  • Worth a short follow-up task to revisit TransformationRepository.mapPackageTo/mapPackageFrom's type safety. The original commit on this branch narrowed the sackage (Input/Output removed) specifically tomake an unresolved Promise a compile-time error — a reasonable goal given this bug's root cause. After merging development into this branch, that narrowing t legitimately pass non-MetadataPackage shapes: DownloadPayloadUseCase/DownloadPayloadFromSyncRuleUseCase (pass SynchronizationPayload, a wider union) and TEID2ApiRepository (passes TrackerPostRequest a bug — by teiTransformations-api.spec.ts,which exercises teiTransformations against DHIS2 wire-format data end-to-end). Reverting to the fully generic signature was the safe choice for this PR's scope, but -leak hole is back open at the type level forany future caller. A follow-up should explore a narrower fix — e.g. a whitelist-style conditional type covering the known valid payload shapes (SynchronizationPayload than touching this again inside an unrelated PR.

xurxodev added 2 commits July 6, 2026 09:29
…convention

The tests hand-rolled every collaborator (vi.fn() objects, a real
DynamicRepositoryFactory instance) instead of using the mock/when/
instance pattern used elsewhere (e.g. MetadataPayloadBuilder.spec.tsx),
and asserted on internal collaborator calls (build()/mapPackageTo()
being invoked) rather than on the use case's observable output.

Rewrote using ts-mockito with givenA... helpers, and simplified the
assertions to what execute() actually persists (package contents,
module version) instead of how it gets there -- the collaborator-call
checks were redundant with those outcome checks and coupled the test
to implementation details.
@xurxodev

xurxodev commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Hi @ifoche, pushed a commit addressing the "Should fix" point from the review:

  • Tests (7edbfe62): rewrote CreatePackageUseCase.spec.ts to use ts-mockito (mock/when/instance) with givenA... helpers, matching the convention used elsewhere (e.g. MetadataPayloadBuilder.spec.tsx), instead of hand-rolled vi.fn() doubles and a real DynamicRepositoryFactory instance.

    While at it, also simplified the assertions: the original tests verified that internal collaborators were called (metadataPayloadBuilder.build(), transformationRepository.mapPackageTo()) rather than the use case's actual observable output. Those collaborator-call checks were redundant — if build() weren't called, or mapPackageTo() were skipped or wrong, the persisted contents would already fail to match, since it flows directly into what's saved. Went with 3 tests focused purely on what execute() persists (package contents resolved instead of a Promise, provided contents used as-is, module version updated), which is both less coupled to implementation and a closer fit to the bug this PR actually fixes.

All 441 tests pass.

The non-blocking recommendation about TransformationRepository.mapPackageTo/mapPackageFrom type safety (reverted to fully generic after merging development) is left as a follow-up, as originally suggested — it needs a proper design (e.g. a whitelist-style conditional type) to avoid breaking DownloadPayloadUseCase/DownloadPayloadFromSyncRuleUseCase/TEID2ApiRepository again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants