feat(types)!: adopt @seamless-auth/types for the wire contract - #117
Merged
Conversation
The SDK's request and response types were hand-written and maintained in parallel with the auth API's schemas, so they could drift from what the API actually sends. Credential.lastUsedAt was the proof: typed Date | null while the API serializes an ISO string, so adopter code calling a Date method typechecked and then threw. Alias the published contract instead. The dependency is types-only, imported with import type, so Zod never reaches the browser bundle and the export names adopters import are unchanged. The OAuth code list stays a compile-time Record<OAuthErrorCode, true> for the same reason: it fails to build if the upstream union changes, without importing the runtime list. LoginStartResult and OrganizationSwitchResult Omit the token, subject, and session id the API returns, keeping the existing decision that sessions are carried by cookies and adopters never handle raw tokens. Several types are now more accurate, which is breaking at the type level: credential timestamps are strings, several credential fields are optional, User.phone is nullable, and User.roles is required. tests/wireTypes.test.ts pins these at compile time so a regression fails the build. Closes #115 Closes #116
Contributor
Author
|
Filed the follow-up for the missing type aliases: fells-code/seamless-auth-types#10. Once those ship, |
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 #115. Closes #116.
@seamless-auth/types0.2.0 publishes the auth API's schemas, so the SDK's hand-written request and response types can stop being a parallel copy.Credential.lastUsedAtis the proof that the copy had already drifted: it was typedDate | nullwhile the API serializes an ISO string, so adopter code calling.getTime()typechecked and then threw. That is #116, and it resolves here.Decisions
Types-only. Imported with
import type, so the package's Zod dependency never reaches the browser bundle. Verified:dist/index.jscontains zero references tozodor the package. The one place that wanted a runtime import is the OAuth code list, which is now a compile-timeRecord<OAuthErrorCode, true>insrc/client/errors.ts. It fails to build if the upstream union gains or loses a member, which is what the runtimeSetwas there to guard against.The SDK keeps its own export names. Adopters still import
CredentialandUserfrom@seamless-auth/react; those names are aliases now rather than declarations.Session material stays unexposed.
LoginStartResultandOrganizationSwitchResultOmitthe token, subject, and session id the API returns, preserving the existing decision that sessions are carried by cookies and adopters never handle raw tokens. Aliasing them wholesale would have advertised token handling as part of the public API.Breaking at the type level
No runtime behavior changes, but several types are now accurate, so adopter code that relied on the old ones will not compile:
Credential.lastUsedAtisstring | null | undefined, andcreatedAtis now presentCredential.deviceType,friendlyName,platform,browser, anddeviceInfoare optionalUser.phoneisstring | null,User.rolesis required, andlastLoginis carriedOrganizationtimestamps arestringrather thanstring | DateVersioned as a minor per the 0.x convention in this repo, with a changeset spelling out each change and the
new Date(...)workaround.Verification
tests/wireTypes.test.tspins these shapes at compile time, sincenpm run typecheckcoverstests/. The@ts-expect-errorguards are the real check: iflastUsedAtreverts toDate, the directive becomes unused and the build fails. I confirmed that mechanism fires rather than passing vacuously.Left local, deliberately
The PRF helpers and
SeamlessAuthResultare SDK concerns rather than wire contracts. Separately, five shapes have upstream schemas but no exported type alias (OAuthProvidersResponse,CredentialUpdateResponse, and the three organization envelope responses), so those stay declared here. Worth a follow-up on the types repo to export them.Validation
npm run lint,npm run typecheck,npm run format:check,npm test -- --runInBand(268 passing across 31 suites),npm run build, andnpm run check-npm-buildall pass.