Skip to content

fix: land the deferred @Joined resolution in main (01B) - #22

Merged
Upd4ting merged 1 commit into
mainfrom
tmp/fixes-batch
Aug 5, 2026
Merged

fix: land the deferred @Joined resolution in main (01B)#22
Upd4ting merged 1 commit into
mainfrom
tmp/fixes-batch

Conversation

@MrSociety404

@MrSociety404 MrSociety404 commented Aug 5, 2026

Copy link
Copy Markdown
Member

Consolidates tmp/fixes-batch into main: the @Joined regression fix from #21 (merged 2026-07-28) — Query.List now resolves its own deferred joined fields, so consumers (the cms members list among them) get populated results again without any change on their side.

The branch was never consolidated, so main (and the v0.1.7 release currently on npm) still ships the regression. This must land before the npm publish: publishing from today's main would ship without the fix. Publish plan after merge: release @antelopejs/interface-data-api. (Republish the shell @antelopejs/data-api — stale instruction: nothing consumes the shell module anymore, every consumer imports interface-data-api directly with a range that picks the new version up on install.)

Greptile Summary

The PR makes Query.List return a self-resolving stream for deferred @Joined fields while preserving page-scoped lookups and count efficiency.

  • Adds operation-aware deferred join materialization for stream consumers.
  • Keeps the default list route in explicit deferred-field mode so joins occur after pagination and respect plucking.
  • Documents the deferred-resolution behavior and adds coverage for paging, filtering, sorting, aggregation, embedding, casting, and iteration.

Confidence Score: 5/5

The PR appears safe to merge with no concrete blocking or independently actionable non-blocking issue identified.

The deferred join wrapper preserves joined-field visibility across the tested stream operations while keeping lookups out of count pipelines and after page boundaries where intended.

Important Files Changed

Filename Overview
src/components.ts Introduces the self-resolving deferred-join stream, operation forwarding, and the Query.List option for exposing unresolved joined fields.
src/index.ts Updates the default list route to retain explicit deferred resolution after pagination and field selection.
src/tests/components/deferred_joined.test.ts Adds broad integration coverage for deferred joined fields across stream execution and transformation paths.
docs/10.joined.md Documents when deferred joins materialize and how callers can explicitly manage them.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Query.List] --> B{Joined field needed by filter or sort?}
  B -->|Yes| C[Materialize before count or sort]
  B -->|No| D{Expose deferred fields?}
  D -->|Yes| E[Return raw stream and deferred field set]
  D -->|No| F[Return DeferredJoinedStream]
  F --> G{First operation}
  G -->|slice or nth| H[Page first, then resolve joins]
  G -->|count or eligible aggregate| I[Use raw pipeline]
  G -->|other row-observing operation| J[Resolve joins before operation]
Loading

Reviews (1): Last reviewed commit: "fix: resolve deferred joined fields from..." | Re-trigger Greptile

* fix: resolve deferred joined fields from the List stream itself

Query.List deferred the display-only joined groups and returned their
names as a third tuple element for the list route to materialize on the
page. Consumers that destructure [query, total] alone (the cms
buildFilteredQuery among them) lost that set, so the deferred @joined
fields never resolved: lists came back without the joined columns and
search filters on them matched nothing.

Wrap the returned stream instead: it materializes the deferred groups
itself as soon as an operation can observe them, keeps the lookups
after slice/nth so they still only run on the returned page, skips
them for bare count() calls and for field aggregates on non-joined
fields (left-join lookups change neither the row count nor other
fields, and a joined-field aggregate only materializes its own group),
and attaches changes() to the raw stream since change feeds cannot
carry the lookups. The third tuple element is now empty by default;
the list route opts back into the raw stream with exposeDeferredJoined
to keep restricting the page lookups to the plucked fields, and a
db-less call also returns the raw stream with the unresolved names
since no lookup can be built without a database.

* docs: document deferred joined resolution on lists

* fix: keep nth() joins on the stream form and document the paging caveat

Routing nth() through the datum form of Joined left the temporary
__joined_orig_* key on the returned row: only the stream form drops it,
since neither Datum nor ValueProxy exposes without(). Slice the single
row first and join the stream instead, which also keeps the lookup on
that row alone.

Also correct the docs: the page-only benefit holds while paging is the
first operation the caller applies. A filter, a sort or the lookup
Query.Foreign stages for a @foreign field materializes the groups over
the whole matched set (still outside the count pipeline); callers that
need them strictly on the page have exposeDeferredJoined.
@MrSociety404
MrSociety404 requested a review from Upd4ting August 5, 2026 09:50
@MrSociety404 MrSociety404 self-assigned this Aug 5, 2026
@Upd4ting
Upd4ting merged commit a7dbc6c into main Aug 5, 2026
3 checks passed
@Upd4ting
Upd4ting deleted the tmp/fixes-batch branch August 5, 2026 09:57
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