@authon/js 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -53,7 +53,12 @@ declare class Authon {
53
53
  signUpWithEmail(email: string, password: string, meta?: {
54
54
  displayName?: string;
55
55
  turnstileToken?: string;
56
- }): Promise<AuthonUser>;
56
+ }): Promise<AuthonUser | {
57
+ needsVerification: true;
58
+ email: string;
59
+ }>;
60
+ verifyEmail(email: string, code: string): Promise<AuthonUser>;
61
+ resendVerificationCode(email: string): Promise<void>;
57
62
  signOut(): Promise<void>;
58
63
  getUser(): AuthonUser | null;
59
64
  getToken(): string | null;
package/dist/index.d.ts CHANGED
@@ -53,7 +53,12 @@ declare class Authon {
53
53
  signUpWithEmail(email: string, password: string, meta?: {
54
54
  displayName?: string;
55
55
  turnstileToken?: string;
56
- }): Promise<AuthonUser>;
56
+ }): Promise<AuthonUser | {
57
+ needsVerification: true;
58
+ email: string;
59
+ }>;
60
+ verifyEmail(email: string, code: string): Promise<AuthonUser>;
61
+ resendVerificationCode(email: string): Promise<void>;
57
62
  signOut(): Promise<void>;
58
63
  getUser(): AuthonUser | null;
59
64
  getToken(): string | null;
package/dist/index.js CHANGED
@@ -805,6 +805,53 @@ var ModalRenderer = class {
805
805
  if (!this.shadowRoot) return;
806
806
  this.shadowRoot.getElementById("authon-error-msg")?.remove();
807
807
  }
808
+ showVerificationInput(email, onVerify, onResend) {
809
+ if (!this.shadowRoot) return;
810
+ const inner = this.shadowRoot.querySelector(".modal-inner");
811
+ if (!inner) return;
812
+ inner.innerHTML = `
813
+ <div style="text-align:center;padding:8px 0">
814
+ <div style="width:48px;height:48px;border-radius:12px;background:color-mix(in srgb, var(--authon-primary-start) 15%, transparent);display:flex;align-items:center;justify-content:center;margin:0 auto 16px">
815
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="var(--authon-primary-start)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>
816
+ </div>
817
+ <h2 class="title" style="font-size:20px;margin-bottom:4px">${this.t.welcomeBack.includes("Welcome") ? "Check your email" : this.t.welcomeBack}</h2>
818
+ <p style="font-size:13px;color:var(--authon-muted);margin-bottom:20px">${email}</p>
819
+ </div>
820
+ <div class="email-form" id="verify-form">
821
+ <input type="text" id="verify-code" class="input" placeholder="000000" maxlength="6" inputmode="numeric" autocomplete="one-time-code" style="text-align:center;font-size:20px;letter-spacing:0.2em;font-family:ui-monospace,monospace" />
822
+ <button type="button" id="verify-submit" class="submit-btn">${this.t.signIn}</button>
823
+ </div>
824
+ <p style="text-align:center;margin-top:12px;font-size:12px;color:var(--authon-dim)">
825
+ <a href="#" id="resend-link" style="color:var(--authon-primary-start);text-decoration:none;font-weight:500">${this.t.backToSignIn.includes("Back") ? "Resend code" : this.t.backToSignIn}</a>
826
+ </p>
827
+ `;
828
+ const codeInput = this.shadowRoot.getElementById("verify-code");
829
+ const submitBtn = this.shadowRoot.getElementById("verify-submit");
830
+ const resendLink = this.shadowRoot.getElementById("resend-link");
831
+ codeInput?.focus();
832
+ codeInput?.addEventListener("input", () => {
833
+ codeInput.value = codeInput.value.replace(/\D/g, "").slice(0, 6);
834
+ });
835
+ submitBtn?.addEventListener("click", async () => {
836
+ const code = codeInput?.value?.trim();
837
+ if (!code || code.length < 6) return;
838
+ submitBtn.textContent = "...";
839
+ submitBtn.disabled = true;
840
+ await onVerify(code);
841
+ });
842
+ codeInput?.addEventListener("keydown", (e) => {
843
+ if (e.key === "Enter") submitBtn?.click();
844
+ });
845
+ resendLink?.addEventListener("click", async (e) => {
846
+ e.preventDefault();
847
+ resendLink.textContent = "...";
848
+ await onResend();
849
+ resendLink.textContent = "Sent!";
850
+ setTimeout(() => {
851
+ resendLink.textContent = "Resend code";
852
+ }, 2e3);
853
+ });
854
+ }
808
855
  showLoading() {
809
856
  if (!this.shadowRoot) return;
810
857
  this.hideLoading();
@@ -3003,14 +3050,27 @@ var Authon = class {
3003
3050
  return res.user;
3004
3051
  }
3005
3052
  async signUpWithEmail(email, password, meta) {
3006
- const tokens = await this.apiPost("/v1/auth/signup", {
3053
+ const res = await this.apiPost("/v1/auth/signup", {
3007
3054
  email,
3008
3055
  password,
3009
3056
  ...meta
3010
3057
  });
3011
- this.session.setSession(tokens);
3012
- this.emit("signedIn", tokens.user);
3013
- return tokens.user;
3058
+ if (res.needsVerification) {
3059
+ this.emit("verificationRequired", res.email);
3060
+ return { needsVerification: true, email: res.email };
3061
+ }
3062
+ this.session.setSession(res);
3063
+ this.emit("signedIn", res.user);
3064
+ return res.user;
3065
+ }
3066
+ async verifyEmail(email, code) {
3067
+ const res = await this.apiPost("/v1/auth/verify-email", { email, code });
3068
+ this.session.setSession(res);
3069
+ this.emit("signedIn", res.user);
3070
+ return res.user;
3071
+ }
3072
+ async resendVerificationCode(email) {
3073
+ await this.apiPost("/v1/auth/resend-code", { email });
3014
3074
  }
3015
3075
  async signOut() {
3016
3076
  await this.session.signOut();
@@ -3361,13 +3421,37 @@ var Authon = class {
3361
3421
  onEmailSubmit: (email, password, isSignUp) => {
3362
3422
  this.modal?.clearError();
3363
3423
  const turnstileToken = this.modal?.getTurnstileToken?.() || void 0;
3364
- const promise = isSignUp ? this.signUpWithEmail(email, password, { turnstileToken }) : this.signInWithEmail(email, password, turnstileToken);
3365
- promise.then(() => this.modal?.close()).catch((err) => {
3366
- this.modal?.resetTurnstile?.();
3367
- const msg = err instanceof Error ? err.message : String(err);
3368
- this.modal?.showError(msg || "Authentication failed");
3369
- this.emit("error", err instanceof Error ? err : new Error(msg));
3370
- });
3424
+ if (isSignUp) {
3425
+ this.signUpWithEmail(email, password, { turnstileToken }).then((result) => {
3426
+ if ("needsVerification" in result && result.needsVerification) {
3427
+ this.modal?.showVerificationInput(email, async (code) => {
3428
+ try {
3429
+ await this.verifyEmail(email, code);
3430
+ this.modal?.close();
3431
+ } catch (err) {
3432
+ const msg = err instanceof Error ? err.message : String(err);
3433
+ this.modal?.showError(msg || "Verification failed");
3434
+ }
3435
+ }, async () => {
3436
+ await this.resendVerificationCode(email);
3437
+ });
3438
+ } else {
3439
+ this.modal?.close();
3440
+ }
3441
+ }).catch((err) => {
3442
+ this.modal?.resetTurnstile?.();
3443
+ const msg = err instanceof Error ? err.message : String(err);
3444
+ this.modal?.showError(msg || "Authentication failed");
3445
+ this.emit("error", err instanceof Error ? err : new Error(msg));
3446
+ });
3447
+ } else {
3448
+ this.signInWithEmail(email, password, turnstileToken).then(() => this.modal?.close()).catch((err) => {
3449
+ this.modal?.resetTurnstile?.();
3450
+ const msg = err instanceof Error ? err.message : String(err);
3451
+ this.modal?.showError(msg || "Authentication failed");
3452
+ this.emit("error", err instanceof Error ? err : new Error(msg));
3453
+ });
3454
+ }
3371
3455
  },
3372
3456
  onClose: () => this.modal?.close(),
3373
3457
  onWeb3WalletSelect: async (walletId) => {