feat(cubejs-client-core): add onlyViews option to meta() - #11391
Conversation
The `/v1/meta` endpoint has supported `?onlyViews=true` since #10809, but no client could reach it — `CubeApi.meta()` hard-coded its request params, so consumers had to go through the private `loadMethod`/`request` pair to filter the data model down to views. Add a `meta()`-specific `MetaMethodOptions` type and forward the flag as the string `'true'`, matching the gateway's `req.query.onlyViews === 'true'` check. The param is spread conditionally, so a `meta()` call without the option produces a byte-identical request to before. Older servers ignore the unknown query param and return the full model. `useCubeMeta` forwards the option through `useCubeFetch` as well. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Claude finished @vasilev-alex's task in 3m 4s —— View job Code review:
|
| # | Severity | Where | Issue |
|---|---|---|---|
| 1 | Medium | client-core/src/index.ts:735 |
onlyViews is added to params for every transport. Over WS, params becomes {"onlyViews":"true"}, and ws/message-schema.ts validates meta params with z.object({}).strict() → 400 Invalid message format. Today meta() works over WS only because {signal: undefined} serializes to {}. Needs onlyViews in the WS schema and in methodParams.meta (ws/subscription-server.ts:21, currently [], which strips unknown keys) — plus a docs note that older servers 400 on WS rather than ignoring. Also suggested sending the boolean instead of 'true': URLSearchParams renders it identically for HTTP, and ApiGateway.meta({ onlyViews?: boolean }) is what the non-HTTP paths receive. |
| 2 | Low | client-react/src/hooks/cube-fetch.js:37 |
refetch({ onlyViews }) is ignored — load() only reads loadOptions.query. Prop-toggle refetch works, so not a blocker. |
What's good
- Conditional spread keeps the no-option request byte-identical — and there's a test asserting exactly that, plus one for
false. That's the right thing to pin down. MetaMethodOptionsasLoadMethodOptions & {…}matches the existingCubeSqlOptionspattern; all three overloads widened consistently.HttpTransporttests assert the actual URL, not just that a param was forwarded — the no-query-string case would catch an accidental?onlyViews=falseor?signal=undefinedregression.- Docblock and docs both state that older servers return the full model, so callers don't treat the response as trusted-filtered. Worth keeping that framing — it's the kind of thing clients otherwise assume.
- React typing tightened from
Omit<CubeFetchOptions, 'query'>(which silently accepted the extra key) to an explicit type. Non-exportedCubeMetaFetchOptionsis consistent with the unexportedCubeFetchOptionsnext to it, so no complaint there.
Security / performance
No concerns. The flag only narrows the model server-side; filterVisibleItemsInMeta still runs after the type === 'view' filter (gateway.ts:714-717), so visibility/security-context filtering is unaffected — this can't widen what a caller sees. Payload reduction is the point, and it's real on large models.
Testing
HTTP coverage is solid. Two gaps:
- No WS-transport test — that's the path finding ReferenceError: self is not defined - Issue with whatwg-fetch when using the core lib with Node.js #1 breaks. A
WebSocketTransporttest asserting the serialized message (or a gateway-sidemessage-schematest accepting{onlyViews: true}) would have caught it. - React side untested; the author acknowledged the package has no harness and verified manually rather than assuming. Reasonable call — introducing test infra belongs in its own PR.
I could not run the suites here: this checkout has no node_modules (no install step in the review job), so yarn unit / yarn lint / tsc --noEmit were not executed. The reported results in the PR body are unverified by me; nothing I found suggests they're wrong.
Documentation
docs-mintlify (correct site — /docs is deprecated) edits look right: new MetaMethodOptions section, meta() signatures updated, usage snippet, and the #metamethodoptions anchor matches the ### \MetaMethodOptions`` heading. If finding #1 is addressed, the WS caveat belongs here too.
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
Addresses review on #11391. `meta({ onlyViews: true })` over `WebSocketTransport` was a hard 400 rather than a silently-ignored flag: `WebSocketTransport.request` puts the whole params object into the message, and `message-schema.ts` validated `meta` params with `z.object({}).strict()`. Today `meta()` works over WS only because `{ signal: undefined }` serializes to `{}`. Allow `onlyViews` in the `meta` params schema and add it to `methodParams` in `subscription-server.ts` — with `[]` the key was stripped before reaching `ApiGateway.meta` even once the schema accepted it. Unknown keys are still rejected. Also send the boolean instead of `'true'` from the client. `URLSearchParams` renders it identically, so the HTTP wire format is unchanged, and the boolean is what `ApiGateway.meta({ onlyViews?: boolean })` expects on the non-HTTP paths. Older servers still reject the flag over WS, so the docblock and docs now distinguish the two transports. `useCubeFetch`'s `refetch({ onlyViews })` now overrides the hook-level value instead of being ignored. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Claude finished @vasilev-alex's task in 2m 2s —— View job Re-review: both prior findings fixed. No blockers; 3 nits, none requiring action.Full reviewTodos
Prior findings — verified fixed#1 (medium) — WS 400. Both halves landed, and the second half was the easy one to miss:
#2 (low) — Both threads resolved. The incidental type fix
New testsThe three
Remaining nits (all optional)
Security / performanceUnchanged from my first pass, and the WS addition doesn't alter it: Verification caveatI could not run any suite: this checkout has no |
|
Both findings addressed in bc91954... Medium (WS 400). Real bug, fixed on the server side as suggested: This does mean the PR now touches the gateway, which it deliberately didn't before. The original scoping assumed "server side already works" — true for HTTP, not for WS. Low ( Docs. The compatibility note is now split by transport: older servers ignore the param over HTTP, but reject the message with a 400 over WS. Same split in the Test results (you noted you couldn't run these — for the record, from a checkout with
On the WS test gap you flagged: the new tests are gateway-side ( |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #11391 +/- ##
===========================================
- Coverage 83.93% 58.99% -24.95%
===========================================
Files 257 223 -34
Lines 80755 17891 -62864
Branches 0 3636 +3636
===========================================
- Hits 67782 10554 -57228
+ Misses 12973 6818 -6155
- Partials 0 519 +519
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
Summary
GET /v1/metahas accepted?onlyViews=truesince #10809 — the gateway readsreq.query.onlyViews === 'true'and passes it to bothmeta()andmetaExtended(),each of which narrows the model with
metaConfig.filter((c) => c.config?.type === 'view')before the usual visibility filtering.
No client could reach it.
CubeApi.meta()hard-coded its request params tosignal/baseRequestId, so anyone wanting views-only had to drop down to theprivate
loadMethod/requestpair. This PR adds the missing client half.Motivation: on large data models the cubes are the bulk of the
/metapayload, andUI surfaces that render only views pay for all of it on every load.
Changes
@cubejs-client/coreMetaMethodOptions = LoadMethodOptions & { onlyViews?: boolean }, exported fromsrc/index.ts.meta()signatures (both overloads + the implementation) widened fromLoadMethodOptionstoMetaMethodOptions.'true', matching the gateway'sreq.query.onlyViews === 'true'check.URLSearchParamswould stringify a boolean identically, but being explicit keeps the wire format visible at the call site.false) the request is byte-identical to today —GET /metawith no query string.@cubejs-client/reactuseCubeFetchforwardsonlyViewsintocoreOptionsfor themetamethod, souseCubeMeta({ onlyViews: true })works.index.d.ts:useCubeMetanow takes ameta-specificCubeMetaFetchOptions(Omit<CubeFetchOptions, 'query'> & { onlyViews?: boolean }) instead of silently accepting an untyped extra key.Docs —
docs-mintlify/.../cubejs-client-core.mdx:meta()now referencesMetaMethodOptions, with a new type section and a usage snippet. Themeta()docblock insrc/index.tsdocuments the option too.Compatibility
metaExtendedbehavior unchanged.Testing
New tests in
packages/cubejs-client-core:CubeApi.test.ts—onlyViews: truereaches the transport as'true'; omitted andfalsesend nothing; the flag coexists withsignal/baseRequestId.HttpTransport.test.ts— wire format:GET /metastays query-string-free by default, and becomesGET /meta?onlyViews=truewith the flag.On the React side
packages/cubejs-client-reacthas no test harness at all (no test script, no runner indevDependencies), so I did not add committed tests there rather than introduce test infra
in this PR — happy to add it if you'd prefer.
I did verify the hook behavior rather than assume it, with a throwaway jsdom + react-dom
render driving
useCubeMetaagainst a stubcubeApi(not committed).useCubeFetch'seffect re-runs on a ramda deep-compare of
options, and toggling the flag does refetch:Note
eslint src/hooks/cube-fetch.jsreports 4 pre-existing errors (lines 23, 42, 48, 65 —operator-linebreak,no-shadow) on lines this PR does not touch; the package'slintscript only globs
src/*.js/src/*.jsx, sosrc/hooksisn't covered today. My changedline is clean.
🤖 Generated with Claude Code