@koolbase/core 10.3.0 → 10.4.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.
@@ -64,6 +64,25 @@ export declare class UnlockTokenInvalidError extends KoolbaseAuthError {
64
64
  export declare class RateLimitError extends KoolbaseAuthError {
65
65
  constructor(message?: string);
66
66
  }
67
+ /**
68
+ * The verification email was refused because one was sent too recently.
69
+ *
70
+ * Carries when the next send becomes possible, so an app can show a countdown
71
+ * rather than a bare refusal — the server sends the timestamp and throwing it
72
+ * away would waste the only thing that makes this error actionable.
73
+ */
74
+ export declare class VerificationResendCooldownError extends KoolbaseAuthError {
75
+ readonly cooldownUntil: Date | null;
76
+ constructor(cooldownUntil: Date | null, message?: string);
77
+ }
78
+ /**
79
+ * The day's verification-email allowance is spent. Distinct from the cooldown
80
+ * because the remedy differs: waiting seconds versus waiting until tomorrow,
81
+ * and an app should say which.
82
+ */
83
+ export declare class VerificationResendDailyCapError extends KoolbaseAuthError {
84
+ constructor(message?: string);
85
+ }
67
86
  /**
68
87
  * Generic network error. The SDK does NOT throw this directly — fetch
69
88
  * failures (DNS, no connection, timeout) propagate as native TypeErrors.
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.GoogleEmailRequiredError = exports.InvalidGoogleTokenError = exports.GoogleSignInNotConfiguredError = exports.OAuthEmailConflictError = exports.AppleEmailRequiredError = exports.InvalidAppleTokenError = exports.AppleSignInNotConfiguredError = exports.SmsConfigMissingError = exports.PhoneAlreadyLinkedError = exports.OtpRateLimitError = exports.OtpMaxAttemptsError = exports.OtpInvalidError = exports.OtpExpiredError = exports.InvalidPhoneNumberError = exports.NetworkError = exports.RateLimitError = exports.UnlockTokenInvalidError = exports.AccountLockedError = exports.TokenRevokedError = exports.SessionExpiredError = exports.WeakPasswordError = exports.UserDisabledError = exports.EmailAlreadyInUseError = exports.InvalidCredentialsError = exports.KoolbaseAuthError = void 0;
3
+ exports.GoogleEmailRequiredError = exports.InvalidGoogleTokenError = exports.GoogleSignInNotConfiguredError = exports.OAuthEmailConflictError = exports.AppleEmailRequiredError = exports.InvalidAppleTokenError = exports.AppleSignInNotConfiguredError = exports.SmsConfigMissingError = exports.PhoneAlreadyLinkedError = exports.OtpRateLimitError = exports.OtpMaxAttemptsError = exports.OtpInvalidError = exports.OtpExpiredError = exports.InvalidPhoneNumberError = exports.NetworkError = exports.VerificationResendDailyCapError = exports.VerificationResendCooldownError = exports.RateLimitError = exports.UnlockTokenInvalidError = exports.AccountLockedError = exports.TokenRevokedError = exports.SessionExpiredError = exports.WeakPasswordError = exports.UserDisabledError = exports.EmailAlreadyInUseError = exports.InvalidCredentialsError = exports.KoolbaseAuthError = void 0;
4
4
  const errors_js_1 = require("./errors.js");
5
5
  /**
6
6
  * Base error type for all Koolbase auth errors. Catchable via
@@ -120,6 +120,35 @@ class RateLimitError extends KoolbaseAuthError {
120
120
  }
121
121
  }
122
122
  exports.RateLimitError = RateLimitError;
123
+ /**
124
+ * The verification email was refused because one was sent too recently.
125
+ *
126
+ * Carries when the next send becomes possible, so an app can show a countdown
127
+ * rather than a bare refusal — the server sends the timestamp and throwing it
128
+ * away would waste the only thing that makes this error actionable.
129
+ */
130
+ class VerificationResendCooldownError extends KoolbaseAuthError {
131
+ constructor(cooldownUntil, message) {
132
+ super(message ?? 'Please wait before requesting another verification email', 'resend_cooldown');
133
+ this.cooldownUntil = cooldownUntil;
134
+ this.name = 'VerificationResendCooldownError';
135
+ Object.setPrototypeOf(this, VerificationResendCooldownError.prototype);
136
+ }
137
+ }
138
+ exports.VerificationResendCooldownError = VerificationResendCooldownError;
139
+ /**
140
+ * The day's verification-email allowance is spent. Distinct from the cooldown
141
+ * because the remedy differs: waiting seconds versus waiting until tomorrow,
142
+ * and an app should say which.
143
+ */
144
+ class VerificationResendDailyCapError extends KoolbaseAuthError {
145
+ constructor(message) {
146
+ super(message ?? 'Daily verification-email limit reached; try again tomorrow', 'resend_daily_cap');
147
+ this.name = 'VerificationResendDailyCapError';
148
+ Object.setPrototypeOf(this, VerificationResendDailyCapError.prototype);
149
+ }
150
+ }
151
+ exports.VerificationResendDailyCapError = VerificationResendDailyCapError;
123
152
  // ─── Network ───────────────────────────────────────────────────────────────
124
153
  /**
125
154
  * Generic network error. The SDK does NOT throw this directly — fetch
@@ -1,4 +1,4 @@
1
- import { AuthStateListener, KoolbaseConfig, KoolbaseSession, KoolbaseUser, LinkPhoneParams, LoginParams, OtpSendResult, PhoneVerifyResult, RegisterParams, RestoreResult, SendOtpParams, SignInWithAppleParams, VerifyOtpParams } from './types.js';
1
+ import { AuthStateListener, KoolbaseConfig, KoolbaseSession, KoolbaseUser, LinkPhoneParams, LoginParams, OtpSendResult, PhoneVerifyResult, RegisterParams, RestoreResult, ResendVerificationResult, SendOtpParams, SignInWithAppleParams, VerifyOtpParams } from './types.js';
2
2
  import type { SignInWithGoogleParams } from './types.js';
3
3
  export declare class KoolbaseAuth {
4
4
  private config;
@@ -143,6 +143,27 @@ export declare class KoolbaseAuth {
143
143
  logout(): Promise<boolean>;
144
144
  forgotPassword(email: string): Promise<void>;
145
145
  resetPassword(token: string, password: string): Promise<void>;
146
+ /**
147
+ * Complete email verification with a token from a verification link.
148
+ *
149
+ * The token comes from wherever your verification URL template pointed —
150
+ * your own page reads it from the query string and passes it here. Throws
151
+ * if the token is invalid, expired or already used.
152
+ */
153
+ verifyEmail(token: string): Promise<void>;
154
+ /**
155
+ * Re-send the verification email to the signed-in but unverified user.
156
+ *
157
+ * Safe to call when already verified: nothing is sent and
158
+ * `alreadyVerified` comes back true. The server throttles this — a short
159
+ * cooldown between sends and a daily cap — and the refusal arrives as
160
+ * VerificationResendCooldownError carrying when to retry, or
161
+ * VerificationResendDailyCapError when the day's allowance is spent.
162
+ *
163
+ * Requires a session, since the server verifies the caller rather than
164
+ * taking an email address — otherwise this would be an open mail relay.
165
+ */
166
+ resendVerificationEmail(): Promise<ResendVerificationResult>;
146
167
  unlock(token: string): Promise<void>;
147
168
  get currentUser(): KoolbaseUser | null;
148
169
  get accessToken(): string | null;
package/dist/cjs/auth.js CHANGED
@@ -503,6 +503,45 @@ class KoolbaseAuth {
503
503
  });
504
504
  await this.checkResponse(res);
505
505
  }
506
+ /**
507
+ * Complete email verification with a token from a verification link.
508
+ *
509
+ * The token comes from wherever your verification URL template pointed —
510
+ * your own page reads it from the query string and passes it here. Throws
511
+ * if the token is invalid, expired or already used.
512
+ */
513
+ async verifyEmail(token) {
514
+ const res = await this.authRequest('/v1/sdk/auth/verify-email', {
515
+ method: 'POST',
516
+ body: { token },
517
+ });
518
+ await this.checkResponse(res);
519
+ }
520
+ /**
521
+ * Re-send the verification email to the signed-in but unverified user.
522
+ *
523
+ * Safe to call when already verified: nothing is sent and
524
+ * `alreadyVerified` comes back true. The server throttles this — a short
525
+ * cooldown between sends and a daily cap — and the refusal arrives as
526
+ * VerificationResendCooldownError carrying when to retry, or
527
+ * VerificationResendDailyCapError when the day's allowance is spent.
528
+ *
529
+ * Requires a session, since the server verifies the caller rather than
530
+ * taking an email address — otherwise this would be an open mail relay.
531
+ */
532
+ async resendVerificationEmail() {
533
+ const res = await this.authRequest('/v1/sdk/auth/resend-verification', {
534
+ method: 'POST',
535
+ includeAuth: true,
536
+ });
537
+ await this.checkResponse(res);
538
+ const body = (await res.json().catch(() => ({})));
539
+ return {
540
+ alreadyVerified: body.already_verified ?? false,
541
+ expiresAt: body.expires_at ? new Date(body.expires_at) : null,
542
+ cooldownUntil: body.cooldown_until ? new Date(body.cooldown_until) : null,
543
+ };
544
+ }
506
545
  async unlock(token) {
507
546
  const res = await this.authRequest('/v1/sdk/auth/unlock', {
508
547
  method: 'POST',
@@ -725,6 +764,10 @@ class KoolbaseAuth {
725
764
  throw new auth_errors_js_1.UnlockTokenInvalidError();
726
765
  case 'rate_limit':
727
766
  throw new auth_errors_js_1.RateLimitError(msg || undefined);
767
+ case 'resend_cooldown':
768
+ throw new auth_errors_js_1.VerificationResendCooldownError(body.cooldown_until ? new Date(body.cooldown_until) : null, msg || undefined);
769
+ case 'resend_daily_cap':
770
+ throw new auth_errors_js_1.VerificationResendDailyCapError(msg || undefined);
728
771
  }
729
772
  // ─── status fallback (pre-code servers) ───
730
773
  if (res.status === 409)
@@ -18,5 +18,5 @@ export type { RegisterTokenOptions } from './messaging.js';
18
18
  export { getOrCreateDeviceId } from './device-id.js';
19
19
  export { koolbaseSdkVersion } from './device-metadata.js';
20
20
  export { RestoreResult } from './types.js';
21
- export type { AuthStateListener, FetchLike, KoolbaseAuthStorage } from './types.js';
21
+ export type { AuthStateListener, FetchLike, KoolbaseAuthStorage, ResendVerificationResult } from './types.js';
22
22
  export { setPlatform, getPlatform, memoryPlatform, type PlatformAdapter, type PlatformStorage, type PlatformNetwork, type PlatformLifecycle, type PlatformLocks, type PlatformInfo, } from './platform.js';
@@ -53,6 +53,23 @@ export interface KoolbaseSession {
53
53
  * unavailable), compliant encryption layers, or in-memory test mocks —
54
54
  * can implement this interface and inject it via KoolbaseConfig.authStorage.
55
55
  */
56
+ /**
57
+ * What resendVerificationEmail() answers with.
58
+ *
59
+ * alreadyVerified is not an error: calling it for a verified account is a
60
+ * no-op that says so, which is what a "resend" button needs when the user
61
+ * verified in another tab.
62
+ *
63
+ * cooldownUntil is when the next send becomes possible. The server throttles
64
+ * sends, and a countdown is a better answer to a user than a bare refusal.
65
+ */
66
+ export interface ResendVerificationResult {
67
+ alreadyVerified: boolean;
68
+ /** When the link in the email stops working. Null when nothing was sent. */
69
+ expiresAt: Date | null;
70
+ /** When another send becomes possible. Null when nothing was sent. */
71
+ cooldownUntil: Date | null;
72
+ }
56
73
  export interface KoolbaseAuthStorage {
57
74
  saveSession(session: KoolbaseSession): Promise<void>;
58
75
  readSession(): Promise<KoolbaseSession | null>;
@@ -64,6 +64,25 @@ export declare class UnlockTokenInvalidError extends KoolbaseAuthError {
64
64
  export declare class RateLimitError extends KoolbaseAuthError {
65
65
  constructor(message?: string);
66
66
  }
67
+ /**
68
+ * The verification email was refused because one was sent too recently.
69
+ *
70
+ * Carries when the next send becomes possible, so an app can show a countdown
71
+ * rather than a bare refusal — the server sends the timestamp and throwing it
72
+ * away would waste the only thing that makes this error actionable.
73
+ */
74
+ export declare class VerificationResendCooldownError extends KoolbaseAuthError {
75
+ readonly cooldownUntil: Date | null;
76
+ constructor(cooldownUntil: Date | null, message?: string);
77
+ }
78
+ /**
79
+ * The day's verification-email allowance is spent. Distinct from the cooldown
80
+ * because the remedy differs: waiting seconds versus waiting until tomorrow,
81
+ * and an app should say which.
82
+ */
83
+ export declare class VerificationResendDailyCapError extends KoolbaseAuthError {
84
+ constructor(message?: string);
85
+ }
67
86
  /**
68
87
  * Generic network error. The SDK does NOT throw this directly — fetch
69
88
  * failures (DNS, no connection, timeout) propagate as native TypeErrors.
@@ -107,6 +107,33 @@ export class RateLimitError extends KoolbaseAuthError {
107
107
  Object.setPrototypeOf(this, RateLimitError.prototype);
108
108
  }
109
109
  }
110
+ /**
111
+ * The verification email was refused because one was sent too recently.
112
+ *
113
+ * Carries when the next send becomes possible, so an app can show a countdown
114
+ * rather than a bare refusal — the server sends the timestamp and throwing it
115
+ * away would waste the only thing that makes this error actionable.
116
+ */
117
+ export class VerificationResendCooldownError extends KoolbaseAuthError {
118
+ constructor(cooldownUntil, message) {
119
+ super(message ?? 'Please wait before requesting another verification email', 'resend_cooldown');
120
+ this.cooldownUntil = cooldownUntil;
121
+ this.name = 'VerificationResendCooldownError';
122
+ Object.setPrototypeOf(this, VerificationResendCooldownError.prototype);
123
+ }
124
+ }
125
+ /**
126
+ * The day's verification-email allowance is spent. Distinct from the cooldown
127
+ * because the remedy differs: waiting seconds versus waiting until tomorrow,
128
+ * and an app should say which.
129
+ */
130
+ export class VerificationResendDailyCapError extends KoolbaseAuthError {
131
+ constructor(message) {
132
+ super(message ?? 'Daily verification-email limit reached; try again tomorrow', 'resend_daily_cap');
133
+ this.name = 'VerificationResendDailyCapError';
134
+ Object.setPrototypeOf(this, VerificationResendDailyCapError.prototype);
135
+ }
136
+ }
110
137
  // ─── Network ───────────────────────────────────────────────────────────────
111
138
  /**
112
139
  * Generic network error. The SDK does NOT throw this directly — fetch
@@ -1,4 +1,4 @@
1
- import { AuthStateListener, KoolbaseConfig, KoolbaseSession, KoolbaseUser, LinkPhoneParams, LoginParams, OtpSendResult, PhoneVerifyResult, RegisterParams, RestoreResult, SendOtpParams, SignInWithAppleParams, VerifyOtpParams } from './types.js';
1
+ import { AuthStateListener, KoolbaseConfig, KoolbaseSession, KoolbaseUser, LinkPhoneParams, LoginParams, OtpSendResult, PhoneVerifyResult, RegisterParams, RestoreResult, ResendVerificationResult, SendOtpParams, SignInWithAppleParams, VerifyOtpParams } from './types.js';
2
2
  import type { SignInWithGoogleParams } from './types.js';
3
3
  export declare class KoolbaseAuth {
4
4
  private config;
@@ -143,6 +143,27 @@ export declare class KoolbaseAuth {
143
143
  logout(): Promise<boolean>;
144
144
  forgotPassword(email: string): Promise<void>;
145
145
  resetPassword(token: string, password: string): Promise<void>;
146
+ /**
147
+ * Complete email verification with a token from a verification link.
148
+ *
149
+ * The token comes from wherever your verification URL template pointed —
150
+ * your own page reads it from the query string and passes it here. Throws
151
+ * if the token is invalid, expired or already used.
152
+ */
153
+ verifyEmail(token: string): Promise<void>;
154
+ /**
155
+ * Re-send the verification email to the signed-in but unverified user.
156
+ *
157
+ * Safe to call when already verified: nothing is sent and
158
+ * `alreadyVerified` comes back true. The server throttles this — a short
159
+ * cooldown between sends and a daily cap — and the refusal arrives as
160
+ * VerificationResendCooldownError carrying when to retry, or
161
+ * VerificationResendDailyCapError when the day's allowance is spent.
162
+ *
163
+ * Requires a session, since the server verifies the caller rather than
164
+ * taking an email address — otherwise this would be an open mail relay.
165
+ */
166
+ resendVerificationEmail(): Promise<ResendVerificationResult>;
146
167
  unlock(token: string): Promise<void>;
147
168
  get currentUser(): KoolbaseUser | null;
148
169
  get accessToken(): string | null;
package/dist/esm/auth.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { RestoreResult, } from './types.js';
2
- import { AccountLockedError, EmailAlreadyInUseError, InvalidCredentialsError, InvalidPhoneNumberError, KoolbaseAuthError, OtpExpiredError, OtpInvalidError, OtpMaxAttemptsError, OtpRateLimitError, PhoneAlreadyLinkedError, RateLimitError, SessionExpiredError, SmsConfigMissingError, TokenRevokedError, UnlockTokenInvalidError, UserDisabledError, WeakPasswordError, AppleEmailRequiredError, AppleSignInNotConfiguredError, InvalidAppleTokenError, OAuthEmailConflictError, GoogleEmailRequiredError, GoogleSignInNotConfiguredError, InvalidGoogleTokenError, } from './auth-errors.js';
2
+ import { AccountLockedError, EmailAlreadyInUseError, InvalidCredentialsError, InvalidPhoneNumberError, KoolbaseAuthError, OtpExpiredError, OtpInvalidError, OtpMaxAttemptsError, OtpRateLimitError, PhoneAlreadyLinkedError, RateLimitError, VerificationResendCooldownError, VerificationResendDailyCapError, SessionExpiredError, SmsConfigMissingError, TokenRevokedError, UnlockTokenInvalidError, UserDisabledError, WeakPasswordError, AppleEmailRequiredError, AppleSignInNotConfiguredError, InvalidAppleTokenError, OAuthEmailConflictError, GoogleEmailRequiredError, GoogleSignInNotConfiguredError, InvalidGoogleTokenError, } from './auth-errors.js';
3
3
  import { getPlatform } from './platform.js';
4
4
  import { DeviceMetadata } from './device-metadata.js';
5
5
  export class KoolbaseAuth {
@@ -500,6 +500,45 @@ export class KoolbaseAuth {
500
500
  });
501
501
  await this.checkResponse(res);
502
502
  }
503
+ /**
504
+ * Complete email verification with a token from a verification link.
505
+ *
506
+ * The token comes from wherever your verification URL template pointed —
507
+ * your own page reads it from the query string and passes it here. Throws
508
+ * if the token is invalid, expired or already used.
509
+ */
510
+ async verifyEmail(token) {
511
+ const res = await this.authRequest('/v1/sdk/auth/verify-email', {
512
+ method: 'POST',
513
+ body: { token },
514
+ });
515
+ await this.checkResponse(res);
516
+ }
517
+ /**
518
+ * Re-send the verification email to the signed-in but unverified user.
519
+ *
520
+ * Safe to call when already verified: nothing is sent and
521
+ * `alreadyVerified` comes back true. The server throttles this — a short
522
+ * cooldown between sends and a daily cap — and the refusal arrives as
523
+ * VerificationResendCooldownError carrying when to retry, or
524
+ * VerificationResendDailyCapError when the day's allowance is spent.
525
+ *
526
+ * Requires a session, since the server verifies the caller rather than
527
+ * taking an email address — otherwise this would be an open mail relay.
528
+ */
529
+ async resendVerificationEmail() {
530
+ const res = await this.authRequest('/v1/sdk/auth/resend-verification', {
531
+ method: 'POST',
532
+ includeAuth: true,
533
+ });
534
+ await this.checkResponse(res);
535
+ const body = (await res.json().catch(() => ({})));
536
+ return {
537
+ alreadyVerified: body.already_verified ?? false,
538
+ expiresAt: body.expires_at ? new Date(body.expires_at) : null,
539
+ cooldownUntil: body.cooldown_until ? new Date(body.cooldown_until) : null,
540
+ };
541
+ }
503
542
  async unlock(token) {
504
543
  const res = await this.authRequest('/v1/sdk/auth/unlock', {
505
544
  method: 'POST',
@@ -722,6 +761,10 @@ export class KoolbaseAuth {
722
761
  throw new UnlockTokenInvalidError();
723
762
  case 'rate_limit':
724
763
  throw new RateLimitError(msg || undefined);
764
+ case 'resend_cooldown':
765
+ throw new VerificationResendCooldownError(body.cooldown_until ? new Date(body.cooldown_until) : null, msg || undefined);
766
+ case 'resend_daily_cap':
767
+ throw new VerificationResendDailyCapError(msg || undefined);
725
768
  }
726
769
  // ─── status fallback (pre-code servers) ───
727
770
  if (res.status === 409)
@@ -18,5 +18,5 @@ export type { RegisterTokenOptions } from './messaging.js';
18
18
  export { getOrCreateDeviceId } from './device-id.js';
19
19
  export { koolbaseSdkVersion } from './device-metadata.js';
20
20
  export { RestoreResult } from './types.js';
21
- export type { AuthStateListener, FetchLike, KoolbaseAuthStorage } from './types.js';
21
+ export type { AuthStateListener, FetchLike, KoolbaseAuthStorage, ResendVerificationResult } from './types.js';
22
22
  export { setPlatform, getPlatform, memoryPlatform, type PlatformAdapter, type PlatformStorage, type PlatformNetwork, type PlatformLifecycle, type PlatformLocks, type PlatformInfo, } from './platform.js';
@@ -53,6 +53,23 @@ export interface KoolbaseSession {
53
53
  * unavailable), compliant encryption layers, or in-memory test mocks —
54
54
  * can implement this interface and inject it via KoolbaseConfig.authStorage.
55
55
  */
56
+ /**
57
+ * What resendVerificationEmail() answers with.
58
+ *
59
+ * alreadyVerified is not an error: calling it for a verified account is a
60
+ * no-op that says so, which is what a "resend" button needs when the user
61
+ * verified in another tab.
62
+ *
63
+ * cooldownUntil is when the next send becomes possible. The server throttles
64
+ * sends, and a countdown is a better answer to a user than a bare refusal.
65
+ */
66
+ export interface ResendVerificationResult {
67
+ alreadyVerified: boolean;
68
+ /** When the link in the email stops working. Null when nothing was sent. */
69
+ expiresAt: Date | null;
70
+ /** When another send becomes possible. Null when nothing was sent. */
71
+ cooldownUntil: Date | null;
72
+ }
56
73
  export interface KoolbaseAuthStorage {
57
74
  saveSession(session: KoolbaseSession): Promise<void>;
58
75
  readSession(): Promise<KoolbaseSession | null>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@koolbase/core",
3
- "version": "10.3.0",
3
+ "version": "10.4.0",
4
4
  "description": "Koolbase SDK core \u2014 shared behaviour behind @koolbase/react-native and @koolbase/js. Install one of those, not this.",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "types": "./dist/esm/index.d.ts",