feat(core): add combine() multi-ref combinator (#270)#282
Merged
Conversation
laazyj
commented
Jul 8, 2026
laazyj
left a comment
Owner
Author
There was a problem hiding this comment.
Shorten the ADR to make it tighter
30f200e to
5f45966
Compare
Contributor
CoverageOverall line coverage: 99.28% across 21 package(s).
|
Add `combine(refs, transform?)` to `@composurecdk/core`: a Ref combinator that resolves a record of Resolvable values against the build context and returns a single Ref to the merged record, optionally transformed. `ref()` reaches exactly one component, so a consumer that assembles a construct from more than one sibling (e.g. a direct API Gateway -> AWS-service AwsIntegration needing both a target's identifier for its VTL template and a credentials role) had no single reference to hand to a Resolvable<T> seam. The workaround was a fake Lifecycle whose only job was to merge two sibling refs -- a graph node modelling no resource. combine closes that gap without new machinery: it returns an ordinary Ref, so it drops into every existing Resolvable seam with no builder change, owns nothing (every sibling stays a first-class compose node), and infers the merged record's types from the input. This is the resolution to #270 chosen over the option B builder in #276, which would have auto-created an IAM role per integration -- net-new behaviour aws-cdk-lib does not provide, obscuring design CDK keeps explicit. The credentials role stays an explicit sibling granted against with consumer-side grants (ADR-0013). Documents the concept in architecture.md, adds ADR-0015 describing the intent and when (not) to use it, and cross-references it from ADR-0013's out-of-scope note. Closes #270
5f45966 to
569b59d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #270. Chosen over the option B builder in #276.
What
Adds
combine(refs, transform?)to@composurecdk/core— a Ref combinator. It resolves a record ofResolvablevalues against the build context and returns a singleRefto the merged record, optionally transformed:Why
ref()reaches exactly one component, so a consumer that assembles a construct from more than one sibling — e.g. a direct API Gateway → AWS-serviceAwsIntegrationneeding both a target's identifier (for its VTL template) and a credentials role — had no single reference to hand to aResolvable<T>seam. The workaround was a fakeLifecyclewhose only job was to merge two sibling refs — acomposegraph node modelling no resource, wired with untyped context casts.combinecloses that gap without new machinery:Ref— drops into every existingResolvable<T>seam (addMethod, …) with no change to any consuming builder, and composes further with.get()/.map().composegraph.Resolved<R>mirrorsresolve()at runtime (aRef<T>yieldsT, a concrete value passes through), so the merged record's keys/types follow from the input and entries may mix refs and concrete values.Why not option B (#276)
The #276 builder's real payload was auto-creating an IAM credentials role per integration — net-new machinery
aws-cdk-libdoes not provide, obscuring a part of the design CDK keeps explicit.combineaddresses the actual, general gap instead; the credentials role stays an explicit sibling granted against with consumer-side grants (ADR-0013). AwsIntegration is just the motivating example —combineapplies wherever one construct is assembled from several siblings.Docs & ADR
docs/architecture.md— new "Combining refs — one consumer, many dependencies" subsection under Ref, with the example and explicit when-not-to-use guidance.ref; permission wiring → consumer-side grants; not an ownership escape hatch). Indexed and cross-referenced from ADR-0013's out-of-scope note.Scope
Core + docs only, one cohesive change. No apigateway surface change, no auto-created roles. Option B's branch/PR #276 is left untouched to close separately.
Testing
7 new unit tests (merge, independent resolution, transform, mixed concrete/ref entries, error propagation,
.map()/.get()composition,Resolvable-seam interchangeability). 100% function/line coverage onref.ts;npm run verifygreen across all 21 projects.