Description
Two paired apollo runtime fixes for OAuth templating. Together they make optional connection_fields (with or without defaults) work correctly across initiate / refresh / exchange_params, and let Mercury declare those fields without ceremony.
1. applyNonEmptyAuthParams — drop keys with empty resolved values
Helper used at 4 oAuth2.ts call sites (authorization_params, token_params, refresh_params POST, refresh_params GET). Drops keys whose resolved value is empty so Mercury closures like team: fields.generic_id don't land as &team= when the user omits the field (Slack rejects that shape — the bug that caused PR #22425 to be reverted).
Setter-callback shape, no instanceof dispatch — same callback writes to URLSearchParams.set / URLSearchParams.append / plain tokenPayload[key] = ... depending on the call site.
2. seedSchemaFieldDefaults — fill schema-declared defaults into the templating data dict
Extends getDataToResolveTemplatesWithEvalFields with an optional authScheme arg. Before resolving eval fields, it walks authScheme.fields[] and seeds any field with a declared default into the leaf-level data dict — but only when the key is absent (caller-supplied data always wins).
This fixes the case where:
- A schema declares an optional field with a default (e.g. Microsoft
issuer: { default: 'common' })
- An existing connection was created before the field was added — its stored connection data has no
issuer key
- Mustache resolves
{{issuer}} to empty → URL becomes login.microsoftonline.com//oauth2/... → Microsoft 404s
With seeding, missing-on-connection fields get filled from schema.default BEFORE templating, so {{issuer}} resolves to 'common' (or whatever the schema declared). 4 call sites of getDataToResolveTemplatesWithEvalFields now pass this.toolkitAuthScheme as the 3rd arg. A previously-bypassed exchange_params site (oAuth2.ts:532) is also routed through the helper for consistency.
Why both in one PR
Both are apollo runtime changes consumed by Mercury #24044. Splitting them across two apollo PRs would force CI to test partial states. The companion package PR (#10058) is now pure schema additions — direct-to-prod safe — and lands first.
How did I test this PR
- 8 new unit tests under
oAuthUtils.test.ts > schema field defaults (PLEN-2153):
- seeds field defaults when absent
- caller wins on conflict
- no seeding without
default
- no-op when authScheme undefined / has no fields array
- seeded default visible to eval-field templating
- Microsoft
issuer existing-connection → 'common'
- Microsoft
issuer user-supplied → passes through
applyNonEmptyAuthParams.unit.test.ts covers empty / undefined / 0 / false / non-string values.
pnpm check-types and pnpm lint clean.
Foolproof / coverage audit (full apollo OAuth templating surface)
Every place apollo templates auth-scheme values now flows through getDataToResolveTemplatesWithEvalFields (which seeds defaults) AND applyNonEmptyAuthParams (which drops empty resolved values):
oAuth2.ts:
- constructor
visitObjectAndTemplate(...) → seeded ✓
authorization_params → non-empty ✓
token_params → non-empty ✓
refresh_params POST → non-empty ✓
refresh_params GET → non-empty ✓
exchange_params (previously bypassed) → seeded ✓
oAuth1.ts constructor → seeded ✓
authorizationData/saml.ts → seeded ✓
getAuthorizationParams.ts → already routed (no change needed)
Sequencing
Merges AFTER #10058 lands. Mercury #24044 merges AFTER both.
Closes PLEN-2153 (apollo portion)
🤖 Generated with Claude Code