Add X-YVP-Sdk header and additionalHeaders override#237
Conversation
🦋 Changeset detectedLatest commit: a9f19de The changes in this PR will be included in the next version bump. This PR includes changesets to release 4 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
cameronapak
left a comment
There was a problem hiding this comment.
Everything looks good to me. I'm considering the script and if it's needed, but... nothing blocking. Good work!
d96d92c to
21e3152
Compare
|
I think you'll need to rebase from main to get this to resolve conflicts. You may have been using an old/stale version of main |
Replace the fragile stamp-sdk-version.mjs script with tsup's define plugin, which injects the version from package.json at build time. This approach: - Eliminates regex fragility - Removes the need for --force rebuilds - Matches the pattern used by Stripe, Sentry, AWS SDKs - Simplifies the release pipeline The version is injected at build time and falls back to 'Dev' at runtime for test environments.
21e3152 to
e1950d8
Compare
|
@Kyleasmth great work. We may need updates to the YouVersionProvider in the UI package. Can you look at that and see if it also needs the headers update? |
|
@cameronapak The UI YouVersionProvider is just a thin wrapper around the hooks one (ComponentProps + {...props} spread), so it picks up additionalHeaders automatically AFAIK. |
Summary
X-YVP-Sdk: ReactSDK={version}on every API call alongsideX-YVP-App-Key, so the data team can attribute traffic to this SDK.packages/core/src/version.ts). Local/dev builds keepDevso they're filterable in the data lake; thereleasescript stamps the precise version frompackages/core/package.jsonbefore the publishing build runs.additionalHeadersprop onYouVersionProvider(andadditionalHeadersfield onApiConfig) merges into every request and overrides built-in headers on key collision. This unblocks the React Native Expo wrapper Cameron flagged on Teams — they can swapX-YVP-Sdk: ReactSDK=...forX-YVP-Sdk: ReactNativeSDK={their version}.Implementation notes
ApiClient.defaultHeaders(the main HTTP path) andYouVersionAPI.addStandardHeaders(the static helper, used by the PKCE auth flow). Both call sites that previously setX-YVP-App-Keynow also setX-YVP-Sdk.config.additionalHeadersis spread last intodefaultHeaders, so caller-supplied values win.YouVersionContext→useBibleClient/useLanguageClient/useHighlights. Provider memoizes the headers object via JSON.stringify so inline object literals don't churn the hook memos.releasescript, withturbo build --forceto bypass the cache from the workflow's earlier (unstamped) build.Known scope gap
Auth requests via
SignInWithYouVersionPKCEuse the staticYouVersionPlatformConfiguration, notApiConfig. They sendX-YVP-Sdkcorrectly but don't honor a provider-leveladditionalHeadersoverride. Out of scope for this ticket auth is typically an OS-level redirect for the React Native case anyway.Test plan
pnpm typecheckclean across all packagespnpm lintclean across all packagespnpm test— 510 tests pass (includes 5 new core cases and 1 new hooks case)pnpm dev:web, open the Next.js example, hit any Bible API call, verify in DevTools → Network:X-Yvp-Sdk: ReactSDK=DevX-Yvp-App-Key: <your key>additionalHeaders={{ 'X-YVP-Sdk': 'ReactNativeSDK=test' }}to<YouVersionProvider>in the example app, confirm header value swaps on the wirenode scripts/stamp-sdk-version.mjsreadspackages/core/package.jsonversion and rewritespackages/core/src/version.ts. The first published version after merge should land with the real semver instead ofDev.Changeset
.changeset/x-yvp-sdk-header.md— minor bump for core / hooks / ui (kept in lockstep perfixed:config).Greptile Summary
This PR attaches an
X-YVP-Sdk: ReactSDK={version}header to every API call and adds anadditionalHeadersescape hatch on bothApiConfigandYouVersionProviderso wrappers (e.g. the React Native Expo SDK) can substitute their own identifier. The version is read at build time by importingpackages/core/package.jsondirectly inversion.ts.X-YVP-Sdkis now set in bothApiClient.defaultHeaders(HTTP path) andYouVersionAPI.addStandardHeaders(static PKCE auth path).additionalHeadersare spread last so caller-supplied values always win on key collision.YouVersionProviderstabilises theadditionalHeadersreference viauseMemokeyed on a sortedJSON.stringifyof entries, preventing unnecessaryApiClientreconstructions from inline object literals. All three hooks (useBibleClient,useLanguageClient,useHighlights) forwardadditionalHeadersinto theirApiClientinstances and include it in their memo dependency arrays.ApiClientunit tests, 1 new hook test, and a new UI provider test file cover the header pass-through and override semantics.Confidence Score: 5/5
Safe to merge. All three API call paths correctly emit the new header, additionalHeaders override semantics work as documented, and the stability memo correctly guards against unnecessary ApiClient reconstructions.
The header wiring is consistent across ApiClient, YouVersionAPI, and all three hooks. The useMemo key-sorting strategy correctly handles insertion-order sensitivity. No incorrect data, dropped state, or auth boundary issues were found in the changed paths.
No files require special attention. The only gap is missing parallel tests for useLanguageClient and useHighlights with additionalHeaders.
Important Files Changed
Sequence Diagram
sequenceDiagram participant App as Consumer App participant YVP as YouVersionProvider participant Ctx as YouVersionContext participant Hook as useBibleClient / useLanguageClient / useHighlights participant AC as ApiClient participant API as YouVersion API App->>YVP: render(appKey, additionalHeaders) YVP->>YVP: "stableAdditionalHeaders = useMemo(sorted JSON key)" YVP->>Ctx: "provide({ appKey, additionalHeaders: stableAdditionalHeaders })" Hook->>Ctx: useContext() Hook->>AC: "new ApiClient({ appKey, additionalHeaders })" AC->>AC: "defaultHeaders = { X-YVP-App-Key, X-YVP-Sdk: ReactSDK={version}, ...additionalHeaders }" Hook->>API: GET /resource (headers: defaultHeaders) API-->>Hook: 200 OK Note over App,API: additionalHeaders override built-ins on key collisionPrompt To Fix All With AI
Reviews (6): Last reviewed commit: "YPE-2295: Test additionalHeaders pass-th..." | Re-trigger Greptile