Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/tidy-moons-tap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@seamless-auth/react': patch
---

Take the last five response envelopes from `@seamless-auth/types` instead of declaring them here. `OAuthProvidersResult`, `CredentialUpdateResult`, `OrganizationResult`, `OrganizationMembersResult`, and `OrganizationMembershipResult` were hand-written because the package had no exported alias for their schemas; types 0.4.0 exports one for every schema, so they are aliases now like the rest. The shapes are identical, so this is a no-op for adopters, and the dependency stays types-only.
8 changes: 4 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,10 @@ Rules for this dependency:
- session material stays unexposed. `LoginStartResult` and
`OrganizationSwitchResult` `Omit` the token, subject, and session id the API
returns, because sessions are carried by cookies here.
- a few shapes have upstream schemas but no exported type alias
(`OAuthProvidersResponse`, `CredentialUpdateResponse`, and the organization
envelope responses). Those stay declared locally until the package exports
them.
- do not redeclare a shape the package already exports. Every exported schema has
a `z.infer` alias as of types 0.4.0, and a test upstream keeps it that way, so
a local interface mirroring a wire shape is a bug. If an alias is genuinely
missing, file it on `seamless-auth-types` rather than working around it.

The PRF helper types and `SeamlessAuthResult` stay local: they are SDK concerns,
not wire contracts.
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
"typescript-eslint": "^8.46.1"
},
"dependencies": {
"@seamless-auth/types": "^0.2.0",
"@seamless-auth/types": "^0.4.0",
"@simplewebauthn/browser": "^13.1.0",
"eslint-plugin-license-header": "^0.9.0",
"libphonenumber-js": "^1.12.7",
Expand Down
28 changes: 10 additions & 18 deletions src/client/createSeamlessAuthClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,17 @@ import {
import type {
AddOrganizationMemberRequest,
CreateOrganizationRequest,
CredentialUpdateResponse,
LoginMethod as LoginMethodShape,
LoginSuccessResponse,
LogoutScope as LogoutScopeShape,
MeResponse,
MessageResponse,
OAuthProvidersResponse,
OrganizationEnvelopeResponse,
OrganizationListResponse,
OrganizationMembersResponse,
OrganizationMembershipEnvelopeResponse,
OrganizationSwitchResponse,
PublicOAuthProvider,
RegistrationRequest,
Expand All @@ -36,7 +41,6 @@ import type {
} from '@seamless-auth/types';

import { createFetchWithAuth } from '../fetchWithAuth';
import { Credential, Organization, OrganizationMembership } from '../types';
import { getWebAuthnErrorDetail } from './errors';
import {
NETWORK_ERROR_STATUS,
Expand Down Expand Up @@ -97,19 +101,12 @@ export type OrganizationMemberUpdateInput = UpdateOrganizationMemberRequest;

export type OrganizationsResult = OrganizationListResponse;

export interface OrganizationResult {
organization: Organization;
}
export type OrganizationResult = OrganizationEnvelopeResponse;

export interface OrganizationMembersResult {
members: OrganizationMembership[];
total: number;
}
export type OrganizationMembersResult = OrganizationMembersResponse;

/** Response body for a single membership mutation. */
export interface OrganizationMembershipResult {
membership: OrganizationMembership;
}
export type OrganizationMembershipResult = OrganizationMembershipEnvelopeResponse;

/**
* Response body when the active organization changes, minus its session
Expand All @@ -122,9 +119,7 @@ export type OrganizationSwitchResult = Omit<

export type OAuthProvider = PublicOAuthProvider;

export interface OAuthProvidersResult {
providers: OAuthProvider[];
}
export type OAuthProvidersResult = OAuthProvidersResponse;

export interface StartOAuthLoginInput {
providerId: string;
Expand Down Expand Up @@ -155,10 +150,7 @@ export interface PasskeyRegistrationData {
}

/** Response body returned when credential metadata is updated. */
export interface CredentialUpdateResult {
message: string;
credential: Credential;
}
export type CredentialUpdateResult = CredentialUpdateResponse;

export interface RegisterPasskeyOptions {
metadata: PasskeyMetadata;
Expand Down
27 changes: 27 additions & 0 deletions tests/wireTypes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@

import type { Credential, Organization, User } from '@/types';
import type {
CredentialUpdateResult,
LoginStartResult,
MessageResult,
OAuthProvidersResult,
OrganizationMembersResult,
OrganizationMembershipResult,
OrganizationResult,
OrganizationSwitchResult,
StepUpStatus,
} from '@/client/createSeamlessAuthClient';
Expand Down Expand Up @@ -58,6 +63,28 @@ describe('wire types match what the API sends', () => {
expect(organizationSwitch.sessionId).toBeUndefined();
});

// These five were declared by hand until the package exported aliases for them
// (seamless-auth-types#10). Pinning the envelopes keeps that from creeping back.
it('takes the response envelopes from the package', () => {
const providers = {} as OAuthProvidersResult;
const organization = {} as OrganizationResult;
const members = {} as OrganizationMembersResult;
const membership = {} as OrganizationMembershipResult;
const credentialUpdate = {} as CredentialUpdateResult;

const providerId: string | undefined = providers.providers?.[0]?.id;
const total: number = members.total;
const lastUsedAt: string | null | undefined = credentialUpdate.credential?.lastUsedAt;

expect([
providerId,
organization.organization,
membership.membership,
total,
lastUsedAt,
]).toHaveLength(5);
});

it('keeps the acknowledgement and step-up shapes intact', () => {
const message: string = '' as MessageResult['message'];
const method: 'webauthn' | 'totp' | null = null as StepUpStatus['method'];
Expand Down
Loading