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
13 changes: 13 additions & 0 deletions .changeset/dedupe-remaining-types.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
"@seamless-auth/core": patch
---

Take the remaining duplicated types from `@seamless-auth/types`.

`SeamlessUser` is now an alias of the types package's `MeUser`, and the eight messaging wire shapes (`MessagingChannel`, `DeliveryResult`, `EmailMessage`, `SmsMessage`, `SendOtpEmailInput`, `SendOtpSmsInput`, `SendMagicLinkEmailInput`, `AuthDeliveryInstruction`) are re-exported rather than declared again. Each was field for field identical to a definition that already existed upstream, which is the drift `@seamless-auth/types` exists to prevent.

What stays declared here is what genuinely belongs to this package: the transport interfaces, which carry provider implementations, and the adopter-facing configuration (`EmailTransport`, `SmsTransport`, `AuthMessageOverrideContext`, `AuthMessageOverrides`, `AuthMessagingHandlers`, `SeamlessAuthMessagingOptions`).

No public API change and no runtime cost. Every name is still exported from `@seamless-auth/core` and both adapters, the re-exports are type-only so they are erased at compile time, and the built output still imports only `@seamless-auth/types/role/matching` at runtime, so neither `zod` nor the schema barrel enters the module graph.

Closes #133.
95 changes: 31 additions & 64 deletions packages/core/src/authMessaging.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,34 @@
export type MessagingChannel = "email" | "sms";
/**
* The messaging contract.
*
* The wire shapes belong to `@seamless-auth/types`, so they are re-exported rather
* than declared again: the auth API sends the delivery instruction and this
* package consumes it, and two definitions of that could drift. The re-export is
* type-only, so it is erased at compile time and neither zod nor the schema
* barrel enters the runtime module graph.
*
* What stays here is what is genuinely this package's: the transport interfaces,
* which carry provider implementations, and the adopter-facing configuration.
*/
export type {
AuthDeliveryInstruction,
DeliveryResult,
EmailMessage,
MessagingChannel,
SendMagicLinkEmailInput,
SendOtpEmailInput,
SendOtpSmsInput,
SmsMessage,
} from "@seamless-auth/types";

export interface DeliveryResult {
accepted: boolean;
provider: string;
channel: MessagingChannel;
messageId?: string;
raw?: unknown;
}

export interface EmailMessage {
to: string;
from?: string;
subject: string;
text: string;
html?: string;
}

export interface SmsMessage {
to: string;
from?: string;
body: string;
}
import type {
DeliveryResult,
EmailMessage,
SendMagicLinkEmailInput,
SendOtpEmailInput,
SendOtpSmsInput,
SmsMessage,
} from "@seamless-auth/types";

export interface EmailTransport {
readonly name: string;
Expand All @@ -32,27 +40,6 @@ export interface SmsTransport {
send(message: SmsMessage): Promise<DeliveryResult>;
}

export interface SendOtpEmailInput {
to: string;
token: string;
from?: string;
subject?: string;
}

export interface SendOtpSmsInput {
to: string;
token: string | number;
from?: string;
}

export interface SendMagicLinkEmailInput {
to: string;
magicLinkUrl: string;
token?: string;
from?: string;
subject?: string;
}

export interface AuthMessageOverrideContext {
appName?: string;
}
Expand All @@ -78,9 +65,7 @@ export interface AuthMessageOverrides {
export interface AuthMessagingHandlers {
sendOtpEmail(input: SendOtpEmailInput): Promise<DeliveryResult>;
sendOtpSms(input: SendOtpSmsInput): Promise<DeliveryResult>;
sendMagicLinkEmail(
input: SendMagicLinkEmailInput,
): Promise<DeliveryResult>;
sendMagicLinkEmail(input: SendMagicLinkEmailInput): Promise<DeliveryResult>;
}

export interface SeamlessAuthMessagingOptions {
Expand All @@ -94,21 +79,3 @@ export interface SeamlessAuthMessagingOptions {
smsFrom?: string;
};
}

export type AuthDeliveryInstruction =
| {
kind: "otp_email";
to: string;
token: string;
}
| {
kind: "otp_sms";
to: string;
token: string | number;
}
| {
kind: "magic_link_email";
to: string;
token?: string;
magicLinkUrl: string;
};
18 changes: 10 additions & 8 deletions packages/core/src/getSeamlessUser.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { MeUser } from "@seamless-auth/types";

import { verifyCookieJwt } from "./verifyCookieJwt.js";
import { authFetch } from "./authFetch.js";
import { assertSecretStrength } from "./validateSecrets.js";
Expand All @@ -8,14 +10,14 @@ import { assertSecretStrength } from "./validateSecrets.js";
* `lastLogin` is an ISO 8601 timestamp, null until the user's first login.
* `activeOrganizationId` is null when the access token carries no org context.
*/
export interface SeamlessUser {
id: string;
email: string;
phone: string | null;
roles: string[];
lastLogin?: string | null;
activeOrganizationId?: string | null;
}
/**
* The caller's own user record, hydrated from the auth API. Distinct from
* `SeamlessAuthUser`, which is only what the access cookie carries.
*
* Aliased to the types package's `MeUser` rather than declared again. The name
* stays `SeamlessUser` here because that is what adapters and adopters import.
*/
export type SeamlessUser = MeUser;

export interface GetSeamlessUserOptions {
authServerUrl: string;
Expand Down
Loading