@koolbase/core 12.0.0 → 12.2.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/cjs/auth-errors.d.ts +34 -0
- package/dist/cjs/auth-errors.js +71 -1
- package/dist/cjs/auth.d.ts +72 -6
- package/dist/cjs/auth.js +168 -10
- package/dist/cjs/database-errors.d.ts +46 -0
- package/dist/cjs/database-errors.js +71 -1
- package/dist/cjs/fiscal.d.ts +114 -0
- package/dist/cjs/fiscal.js +167 -0
- package/dist/cjs/index.d.ts +2 -0
- package/dist/cjs/index.js +7 -1
- package/dist/esm/auth-errors.d.ts +34 -0
- package/dist/esm/auth-errors.js +63 -0
- package/dist/esm/auth.d.ts +72 -6
- package/dist/esm/auth.js +169 -11
- package/dist/esm/database-errors.d.ts +46 -0
- package/dist/esm/database-errors.js +66 -0
- package/dist/esm/fiscal.d.ts +114 -0
- package/dist/esm/fiscal.js +159 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +1 -0
- package/package.json +1 -1
|
@@ -101,6 +101,14 @@ export declare class NetworkError extends KoolbaseAuthError {
|
|
|
101
101
|
export declare class InvalidPhoneNumberError extends KoolbaseAuthError {
|
|
102
102
|
constructor();
|
|
103
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* The project has switched off signing in with an emailed code — 403
|
|
106
|
+
* `email_code_disabled`. Applies to every address alike, so it reveals
|
|
107
|
+
* nothing about which accounts exist.
|
|
108
|
+
*/
|
|
109
|
+
export declare class EmailCodeDisabledError extends KoolbaseAuthError {
|
|
110
|
+
constructor();
|
|
111
|
+
}
|
|
104
112
|
export declare class OtpExpiredError extends KoolbaseAuthError {
|
|
105
113
|
constructor();
|
|
106
114
|
}
|
|
@@ -249,3 +257,29 @@ export declare class InvalidGoogleTokenError extends KoolbaseAuthError {
|
|
|
249
257
|
export declare class GoogleEmailRequiredError extends KoolbaseAuthError {
|
|
250
258
|
constructor();
|
|
251
259
|
}
|
|
260
|
+
/**
|
|
261
|
+
* The first factor passed and this account needs a second: sign-in is not
|
|
262
|
+
* finished. Pass `challengeToken` to `verifyMfa` with a code from the
|
|
263
|
+
* person's authenticator app, or to `verifyRecoveryCode`. Apps that never
|
|
264
|
+
* enable MFA never see this.
|
|
265
|
+
*/
|
|
266
|
+
export declare class MfaRequiredError extends KoolbaseAuthError {
|
|
267
|
+
readonly challengeToken: string;
|
|
268
|
+
readonly expiresAt?: string;
|
|
269
|
+
constructor(challengeToken: string, expiresAt?: string);
|
|
270
|
+
}
|
|
271
|
+
export declare class RecentAuthRequiredError extends KoolbaseAuthError {
|
|
272
|
+
constructor();
|
|
273
|
+
}
|
|
274
|
+
export declare class RecentMfaRequiredError extends KoolbaseAuthError {
|
|
275
|
+
constructor();
|
|
276
|
+
}
|
|
277
|
+
export declare class MfaAlreadyEnabledError extends KoolbaseAuthError {
|
|
278
|
+
constructor();
|
|
279
|
+
}
|
|
280
|
+
export declare class MfaEnrollmentNotFoundError extends KoolbaseAuthError {
|
|
281
|
+
constructor();
|
|
282
|
+
}
|
|
283
|
+
export declare class MfaNotEnabledError extends KoolbaseAuthError {
|
|
284
|
+
constructor();
|
|
285
|
+
}
|
package/dist/cjs/auth-errors.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.GoogleEmailRequiredError = exports.InvalidGoogleTokenError = exports.MalformedSessionResponseError = exports.ProviderIdentityAlreadyLinkedError = exports.IdentityNotFoundError = exports.InsufficientScopeError = exports.HideRequiresVerificationError = exports.LastCredentialError = exports.InsufficientAuthorityError = exports.SessionRequiredError = exports.UnsupportedOAuthProviderError = exports.OAuthOnlyAccountError = exports.AccountExistsError = exports.CurrentPasswordIncorrectError = exports.TokenAlreadyUsedError = exports.TokenExpiredError = exports.SignupsDisabledError = exports.ContactNotVerifiedError = 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;
|
|
3
|
+
exports.MfaNotEnabledError = exports.MfaEnrollmentNotFoundError = exports.MfaAlreadyEnabledError = exports.RecentMfaRequiredError = exports.RecentAuthRequiredError = exports.MfaRequiredError = exports.GoogleEmailRequiredError = exports.InvalidGoogleTokenError = exports.MalformedSessionResponseError = exports.ProviderIdentityAlreadyLinkedError = exports.IdentityNotFoundError = exports.InsufficientScopeError = exports.HideRequiresVerificationError = exports.LastCredentialError = exports.InsufficientAuthorityError = exports.SessionRequiredError = exports.UnsupportedOAuthProviderError = exports.OAuthOnlyAccountError = exports.AccountExistsError = exports.CurrentPasswordIncorrectError = exports.TokenAlreadyUsedError = exports.TokenExpiredError = exports.SignupsDisabledError = exports.ContactNotVerifiedError = exports.GoogleSignInNotConfiguredError = exports.OAuthEmailConflictError = exports.AppleEmailRequiredError = exports.InvalidAppleTokenError = exports.AppleSignInNotConfiguredError = exports.SmsConfigMissingError = exports.PhoneAlreadyLinkedError = exports.OtpRateLimitError = exports.OtpMaxAttemptsError = exports.OtpInvalidError = exports.OtpExpiredError = exports.EmailCodeDisabledError = 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
|
|
@@ -179,6 +179,19 @@ class InvalidPhoneNumberError extends KoolbaseAuthError {
|
|
|
179
179
|
}
|
|
180
180
|
}
|
|
181
181
|
exports.InvalidPhoneNumberError = InvalidPhoneNumberError;
|
|
182
|
+
/**
|
|
183
|
+
* The project has switched off signing in with an emailed code — 403
|
|
184
|
+
* `email_code_disabled`. Applies to every address alike, so it reveals
|
|
185
|
+
* nothing about which accounts exist.
|
|
186
|
+
*/
|
|
187
|
+
class EmailCodeDisabledError extends KoolbaseAuthError {
|
|
188
|
+
constructor() {
|
|
189
|
+
super('Signing in with an emailed code is switched off for this project', 'email_code_disabled');
|
|
190
|
+
this.name = 'EmailCodeDisabledError';
|
|
191
|
+
Object.setPrototypeOf(this, EmailCodeDisabledError.prototype);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
exports.EmailCodeDisabledError = EmailCodeDisabledError;
|
|
182
195
|
class OtpExpiredError extends KoolbaseAuthError {
|
|
183
196
|
constructor() {
|
|
184
197
|
super('OTP has expired, please request a new code', 'otp_expired');
|
|
@@ -472,3 +485,60 @@ class GoogleEmailRequiredError extends KoolbaseAuthError {
|
|
|
472
485
|
}
|
|
473
486
|
}
|
|
474
487
|
exports.GoogleEmailRequiredError = GoogleEmailRequiredError;
|
|
488
|
+
// ─── Two-step sign-in (MFA) ─────────────────────────────────────────────────
|
|
489
|
+
/**
|
|
490
|
+
* The first factor passed and this account needs a second: sign-in is not
|
|
491
|
+
* finished. Pass `challengeToken` to `verifyMfa` with a code from the
|
|
492
|
+
* person's authenticator app, or to `verifyRecoveryCode`. Apps that never
|
|
493
|
+
* enable MFA never see this.
|
|
494
|
+
*/
|
|
495
|
+
class MfaRequiredError extends KoolbaseAuthError {
|
|
496
|
+
constructor(challengeToken, expiresAt) {
|
|
497
|
+
super('Two-step sign-in required', 'mfa_required');
|
|
498
|
+
this.name = 'MfaRequiredError';
|
|
499
|
+
this.challengeToken = challengeToken;
|
|
500
|
+
this.expiresAt = expiresAt;
|
|
501
|
+
Object.setPrototypeOf(this, MfaRequiredError.prototype);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
exports.MfaRequiredError = MfaRequiredError;
|
|
505
|
+
class RecentAuthRequiredError extends KoolbaseAuthError {
|
|
506
|
+
constructor() {
|
|
507
|
+
super('Sign in again to change two-step sign-in', 'recent_auth_required');
|
|
508
|
+
this.name = 'RecentAuthRequiredError';
|
|
509
|
+
Object.setPrototypeOf(this, RecentAuthRequiredError.prototype);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
exports.RecentAuthRequiredError = RecentAuthRequiredError;
|
|
513
|
+
class RecentMfaRequiredError extends KoolbaseAuthError {
|
|
514
|
+
constructor() {
|
|
515
|
+
super('Confirm with your authenticator first', 'recent_mfa_required');
|
|
516
|
+
this.name = 'RecentMfaRequiredError';
|
|
517
|
+
Object.setPrototypeOf(this, RecentMfaRequiredError.prototype);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
exports.RecentMfaRequiredError = RecentMfaRequiredError;
|
|
521
|
+
class MfaAlreadyEnabledError extends KoolbaseAuthError {
|
|
522
|
+
constructor() {
|
|
523
|
+
super('Two-step sign-in is already on for this account', 'mfa_already_enabled');
|
|
524
|
+
this.name = 'MfaAlreadyEnabledError';
|
|
525
|
+
Object.setPrototypeOf(this, MfaAlreadyEnabledError.prototype);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
exports.MfaAlreadyEnabledError = MfaAlreadyEnabledError;
|
|
529
|
+
class MfaEnrollmentNotFoundError extends KoolbaseAuthError {
|
|
530
|
+
constructor() {
|
|
531
|
+
super('No enrolment in progress; start again', 'mfa_enrollment_not_found');
|
|
532
|
+
this.name = 'MfaEnrollmentNotFoundError';
|
|
533
|
+
Object.setPrototypeOf(this, MfaEnrollmentNotFoundError.prototype);
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
exports.MfaEnrollmentNotFoundError = MfaEnrollmentNotFoundError;
|
|
537
|
+
class MfaNotEnabledError extends KoolbaseAuthError {
|
|
538
|
+
constructor() {
|
|
539
|
+
super('Two-step sign-in is not on for this account', 'mfa_not_enabled');
|
|
540
|
+
this.name = 'MfaNotEnabledError';
|
|
541
|
+
Object.setPrototypeOf(this, MfaNotEnabledError.prototype);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
exports.MfaNotEnabledError = MfaNotEnabledError;
|
package/dist/cjs/auth.d.ts
CHANGED
|
@@ -302,12 +302,10 @@ export declare class KoolbaseAuth {
|
|
|
302
302
|
validAccessToken(): Promise<string | null>;
|
|
303
303
|
setSession(session: KoolbaseSession | null): Promise<void>;
|
|
304
304
|
/**
|
|
305
|
-
* @deprecated
|
|
306
|
-
*
|
|
307
|
-
*
|
|
308
|
-
*
|
|
309
|
-
* server endpoints under /v1/sdk/auth/oauth/{apple,google,github}.
|
|
310
|
-
* Use email/password sign-in for now.
|
|
305
|
+
* @deprecated Never implemented; kept only so existing code compiles.
|
|
306
|
+
* Google and Apple sign-in are supported — use signInWithGoogle() or
|
|
307
|
+
* signInWithApple(). This used to say OAuth was not yet shipped and to
|
|
308
|
+
* use email and password instead, which stopped being true long ago.
|
|
311
309
|
*
|
|
312
310
|
* @throws Always throws KoolbaseAuthError('not_implemented').
|
|
313
311
|
*/
|
|
@@ -318,6 +316,74 @@ export declare class KoolbaseAuth {
|
|
|
318
316
|
name?: string;
|
|
319
317
|
avatarUrl?: string;
|
|
320
318
|
}): Promise<never>;
|
|
319
|
+
/**
|
|
320
|
+
* Emails a six-digit sign-in code.
|
|
321
|
+
*
|
|
322
|
+
* Resolves the same way whether or not the address has an account, so it
|
|
323
|
+
* cannot be used to check who is registered. A new address receives a code
|
|
324
|
+
* only while the project accepts sign-ups; a disabled account receives
|
|
325
|
+
* nothing.
|
|
326
|
+
*
|
|
327
|
+
* @throws EmailCodeDisabledError if the project has switched this off
|
|
328
|
+
* @throws RateLimitError after too many requests for one address
|
|
329
|
+
*/
|
|
330
|
+
requestEmailCode(params: {
|
|
331
|
+
email: string;
|
|
332
|
+
}): Promise<void>;
|
|
333
|
+
/**
|
|
334
|
+
* Signs in with a code from requestEmailCode(), storing the session exactly
|
|
335
|
+
* as login() does. An unknown address becomes an account only if the
|
|
336
|
+
* project still accepts sign-ups at this moment. Each code works once and
|
|
337
|
+
* allows three attempts.
|
|
338
|
+
*
|
|
339
|
+
* @throws OtpInvalidError, OtpExpiredError, OtpMaxAttemptsError
|
|
340
|
+
* @throws EmailCodeDisabledError if the project has switched this off
|
|
341
|
+
*/
|
|
342
|
+
signInWithEmailCode(params: {
|
|
343
|
+
email: string;
|
|
344
|
+
code: string;
|
|
345
|
+
}): Promise<KoolbaseSession>;
|
|
346
|
+
private mfaRequired;
|
|
347
|
+
/** Finishes sign-in with a code from the person's authenticator app. */
|
|
348
|
+
verifyMfa(params: {
|
|
349
|
+
challengeToken: string;
|
|
350
|
+
code: string;
|
|
351
|
+
}): Promise<KoolbaseSession>;
|
|
352
|
+
/**
|
|
353
|
+
* Finishes sign-in with a recovery code. Each works once; prompt the person
|
|
354
|
+
* to regenerate when recoveryCodesRemaining reaches zero.
|
|
355
|
+
*/
|
|
356
|
+
verifyRecoveryCode(params: {
|
|
357
|
+
challengeToken: string;
|
|
358
|
+
code: string;
|
|
359
|
+
}): Promise<{
|
|
360
|
+
session: KoolbaseSession;
|
|
361
|
+
recoveryCodesRemaining: number;
|
|
362
|
+
}>;
|
|
363
|
+
/**
|
|
364
|
+
* Starts adding an authenticator; needs a sign-in within ten minutes. Show
|
|
365
|
+
* otpauthUri as a QR code, then call confirmMfaEnrollment with the first
|
|
366
|
+
* code the app shows.
|
|
367
|
+
*/
|
|
368
|
+
enrollMfa(): Promise<{
|
|
369
|
+
otpauthUri: string;
|
|
370
|
+
secret: string;
|
|
371
|
+
}>;
|
|
372
|
+
/** Turns MFA on and returns ten recovery codes, shown this once only. Other devices are signed out. */
|
|
373
|
+
confirmMfaEnrollment(code: string): Promise<string[]>;
|
|
374
|
+
mfaStatus(): Promise<{
|
|
375
|
+
enabled: boolean;
|
|
376
|
+
recoveryCodesRemaining: number;
|
|
377
|
+
}>;
|
|
378
|
+
/** Re-confirms the second factor, opening ten minutes to change MFA. */
|
|
379
|
+
stepUpMfa(params: {
|
|
380
|
+
code?: string;
|
|
381
|
+
recoveryCode?: string;
|
|
382
|
+
}): Promise<void>;
|
|
383
|
+
/** Turns MFA off. Needs stepUpMfa() within the last ten minutes. */
|
|
384
|
+
disableMfa(): Promise<void>;
|
|
385
|
+
/** Replaces all recovery codes; the old ones stop working. Needs stepUpMfa() within ten minutes. */
|
|
386
|
+
regenerateRecoveryCodes(): Promise<string[]>;
|
|
321
387
|
sendOtp(params: SendOtpParams): Promise<OtpSendResult>;
|
|
322
388
|
verifyOtp(params: VerifyOtpParams): Promise<PhoneVerifyResult>;
|
|
323
389
|
linkPhone(params: LinkPhoneParams): Promise<void>;
|
package/dist/cjs/auth.js
CHANGED
|
@@ -388,6 +388,8 @@ class KoolbaseAuth {
|
|
|
388
388
|
const errorMessage = body?.error ?? '';
|
|
389
389
|
// ─── code-first ───
|
|
390
390
|
switch (code) {
|
|
391
|
+
case 'mfa_required':
|
|
392
|
+
throw this.mfaRequired(body);
|
|
391
393
|
case 'oauth_not_configured':
|
|
392
394
|
throw new auth_errors_js_1.GoogleSignInNotConfiguredError();
|
|
393
395
|
case 'invalid_oauth_token':
|
|
@@ -442,6 +444,8 @@ class KoolbaseAuth {
|
|
|
442
444
|
const errorMessage = body?.error ?? '';
|
|
443
445
|
// ─── code-first ───
|
|
444
446
|
switch (code) {
|
|
447
|
+
case 'mfa_required':
|
|
448
|
+
throw this.mfaRequired(body);
|
|
445
449
|
case 'oauth_not_configured':
|
|
446
450
|
throw new auth_errors_js_1.AppleSignInNotConfiguredError();
|
|
447
451
|
case 'invalid_oauth_token':
|
|
@@ -824,20 +828,150 @@ class KoolbaseAuth {
|
|
|
824
828
|
}
|
|
825
829
|
// ─── OAuth (DEPRECATED — see v1.10.0) ───────────────────────────────────
|
|
826
830
|
/**
|
|
827
|
-
* @deprecated
|
|
828
|
-
*
|
|
829
|
-
*
|
|
830
|
-
*
|
|
831
|
-
* server endpoints under /v1/sdk/auth/oauth/{apple,google,github}.
|
|
832
|
-
* Use email/password sign-in for now.
|
|
831
|
+
* @deprecated Never implemented; kept only so existing code compiles.
|
|
832
|
+
* Google and Apple sign-in are supported — use signInWithGoogle() or
|
|
833
|
+
* signInWithApple(). This used to say OAuth was not yet shipped and to
|
|
834
|
+
* use email and password instead, which stopped being true long ago.
|
|
833
835
|
*
|
|
834
836
|
* @throws Always throws KoolbaseAuthError('not_implemented').
|
|
835
837
|
*/
|
|
836
838
|
async oauthLogin(_params) {
|
|
837
|
-
throw new auth_errors_js_1.KoolbaseAuthError('
|
|
838
|
-
'
|
|
839
|
-
|
|
840
|
-
|
|
839
|
+
throw new auth_errors_js_1.KoolbaseAuthError('oauthLogin() was never implemented and is kept only so existing ' +
|
|
840
|
+
'code compiles. Use signInWithGoogle() or signInWithApple().', 'not_implemented');
|
|
841
|
+
}
|
|
842
|
+
// ─── Email code ─────────────────────────────────────────────────────────
|
|
843
|
+
/**
|
|
844
|
+
* Emails a six-digit sign-in code.
|
|
845
|
+
*
|
|
846
|
+
* Resolves the same way whether or not the address has an account, so it
|
|
847
|
+
* cannot be used to check who is registered. A new address receives a code
|
|
848
|
+
* only while the project accepts sign-ups; a disabled account receives
|
|
849
|
+
* nothing.
|
|
850
|
+
*
|
|
851
|
+
* @throws EmailCodeDisabledError if the project has switched this off
|
|
852
|
+
* @throws RateLimitError after too many requests for one address
|
|
853
|
+
*/
|
|
854
|
+
async requestEmailCode(params) {
|
|
855
|
+
const res = await this.authRequest('/v1/sdk/auth/email/code', {
|
|
856
|
+
method: 'POST',
|
|
857
|
+
body: { email: params.email },
|
|
858
|
+
});
|
|
859
|
+
if (!res.ok)
|
|
860
|
+
await this.throwTypedError(res, false);
|
|
861
|
+
}
|
|
862
|
+
/**
|
|
863
|
+
* Signs in with a code from requestEmailCode(), storing the session exactly
|
|
864
|
+
* as login() does. An unknown address becomes an account only if the
|
|
865
|
+
* project still accepts sign-ups at this moment. Each code works once and
|
|
866
|
+
* allows three attempts.
|
|
867
|
+
*
|
|
868
|
+
* @throws OtpInvalidError, OtpExpiredError, OtpMaxAttemptsError
|
|
869
|
+
* @throws EmailCodeDisabledError if the project has switched this off
|
|
870
|
+
*/
|
|
871
|
+
async signInWithEmailCode(params) {
|
|
872
|
+
const res = await this.authRequest('/v1/sdk/auth/email/code/verify', {
|
|
873
|
+
method: 'POST',
|
|
874
|
+
body: { email: params.email, code: params.code },
|
|
875
|
+
});
|
|
876
|
+
const session = await this.parseSessionResponse(res, false);
|
|
877
|
+
await this.setSessionInternal(session);
|
|
878
|
+
return session;
|
|
879
|
+
}
|
|
880
|
+
// ─── Two-step sign-in (MFA) ─────────────────────────────────────────────
|
|
881
|
+
//
|
|
882
|
+
// When an account has MFA on, every sign-in method throws MfaRequiredError.
|
|
883
|
+
// Finish with verifyMfa() or verifyRecoveryCode().
|
|
884
|
+
// One builder for every parser, so the four cannot drift apart in how the
|
|
885
|
+
// challenge reaches the app.
|
|
886
|
+
mfaRequired(body) {
|
|
887
|
+
const d = body?.details ?? {};
|
|
888
|
+
return new auth_errors_js_1.MfaRequiredError(String(d.challenge_token ?? ''), d.expires_at);
|
|
889
|
+
}
|
|
890
|
+
/** Finishes sign-in with a code from the person's authenticator app. */
|
|
891
|
+
async verifyMfa(params) {
|
|
892
|
+
const res = await this.authRequest('/v1/sdk/auth/mfa/verify', {
|
|
893
|
+
method: 'POST',
|
|
894
|
+
body: { challenge_token: params.challengeToken, code: params.code },
|
|
895
|
+
});
|
|
896
|
+
const session = await this.parseSessionResponse(res, false);
|
|
897
|
+
await this.setSessionInternal(session);
|
|
898
|
+
return session;
|
|
899
|
+
}
|
|
900
|
+
/**
|
|
901
|
+
* Finishes sign-in with a recovery code. Each works once; prompt the person
|
|
902
|
+
* to regenerate when recoveryCodesRemaining reaches zero.
|
|
903
|
+
*/
|
|
904
|
+
async verifyRecoveryCode(params) {
|
|
905
|
+
const res = await this.authRequest('/v1/sdk/auth/mfa/verify-recovery', {
|
|
906
|
+
method: 'POST',
|
|
907
|
+
body: { challenge_token: params.challengeToken, code: params.code },
|
|
908
|
+
});
|
|
909
|
+
if (!res.ok)
|
|
910
|
+
await this.throwTypedError(res, false);
|
|
911
|
+
// Read once: the session and the remaining count come from one body.
|
|
912
|
+
const data = await res.json();
|
|
913
|
+
if (!data?.access_token)
|
|
914
|
+
throw new auth_errors_js_1.MalformedSessionResponseError('an access token');
|
|
915
|
+
if (!data?.refresh_token)
|
|
916
|
+
throw new auth_errors_js_1.MalformedSessionResponseError('a refresh token');
|
|
917
|
+
const session = {
|
|
918
|
+
accessToken: data.access_token,
|
|
919
|
+
refreshToken: data.refresh_token,
|
|
920
|
+
expiresAt: data.expires_at,
|
|
921
|
+
user: this.mapUser(data.user),
|
|
922
|
+
};
|
|
923
|
+
await this.setSessionInternal(session);
|
|
924
|
+
return { session, recoveryCodesRemaining: Number(data.recovery_codes_remaining ?? 0) };
|
|
925
|
+
}
|
|
926
|
+
/**
|
|
927
|
+
* Starts adding an authenticator; needs a sign-in within ten minutes. Show
|
|
928
|
+
* otpauthUri as a QR code, then call confirmMfaEnrollment with the first
|
|
929
|
+
* code the app shows.
|
|
930
|
+
*/
|
|
931
|
+
async enrollMfa() {
|
|
932
|
+
const res = await this.authRequest('/v1/sdk/auth/mfa/enroll', { method: 'POST', includeAuth: true });
|
|
933
|
+
await this.checkResponse(res);
|
|
934
|
+
const d = await res.json();
|
|
935
|
+
return { otpauthUri: d.otpauth_uri, secret: d.secret };
|
|
936
|
+
}
|
|
937
|
+
/** Turns MFA on and returns ten recovery codes, shown this once only. Other devices are signed out. */
|
|
938
|
+
async confirmMfaEnrollment(code) {
|
|
939
|
+
const res = await this.authRequest('/v1/sdk/auth/mfa/enroll/confirm', {
|
|
940
|
+
method: 'POST',
|
|
941
|
+
body: { code },
|
|
942
|
+
includeAuth: true,
|
|
943
|
+
});
|
|
944
|
+
await this.checkResponse(res);
|
|
945
|
+
return (await res.json()).recovery_codes;
|
|
946
|
+
}
|
|
947
|
+
async mfaStatus() {
|
|
948
|
+
const res = await this.authRequest('/v1/sdk/auth/mfa', { method: 'GET', includeAuth: true });
|
|
949
|
+
await this.checkResponse(res);
|
|
950
|
+
const d = await res.json();
|
|
951
|
+
return { enabled: !!d.enabled, recoveryCodesRemaining: Number(d.recovery_codes_remaining ?? 0) };
|
|
952
|
+
}
|
|
953
|
+
/** Re-confirms the second factor, opening ten minutes to change MFA. */
|
|
954
|
+
async stepUpMfa(params) {
|
|
955
|
+
const res = await this.authRequest('/v1/sdk/auth/mfa/step-up', {
|
|
956
|
+
method: 'POST',
|
|
957
|
+
body: {
|
|
958
|
+
...(params.code ? { code: params.code } : {}),
|
|
959
|
+
...(params.recoveryCode ? { recovery_code: params.recoveryCode } : {}),
|
|
960
|
+
},
|
|
961
|
+
includeAuth: true,
|
|
962
|
+
});
|
|
963
|
+
await this.checkResponse(res);
|
|
964
|
+
}
|
|
965
|
+
/** Turns MFA off. Needs stepUpMfa() within the last ten minutes. */
|
|
966
|
+
async disableMfa() {
|
|
967
|
+
const res = await this.authRequest('/v1/sdk/auth/mfa/disable', { method: 'POST', includeAuth: true });
|
|
968
|
+
await this.checkResponse(res);
|
|
969
|
+
}
|
|
970
|
+
/** Replaces all recovery codes; the old ones stop working. Needs stepUpMfa() within ten minutes. */
|
|
971
|
+
async regenerateRecoveryCodes() {
|
|
972
|
+
const res = await this.authRequest('/v1/sdk/auth/mfa/recovery-codes', { method: 'POST', includeAuth: true });
|
|
973
|
+
await this.checkResponse(res);
|
|
974
|
+
return (await res.json()).recovery_codes;
|
|
841
975
|
}
|
|
842
976
|
// ─── Phone OTP ──────────────────────────────────────────────────────────
|
|
843
977
|
async sendOtp(params) {
|
|
@@ -1006,6 +1140,18 @@ class KoolbaseAuth {
|
|
|
1006
1140
|
const msg = body.error ?? '';
|
|
1007
1141
|
// ─── code-first ───
|
|
1008
1142
|
switch (code) {
|
|
1143
|
+
case 'mfa_required':
|
|
1144
|
+
throw this.mfaRequired(body);
|
|
1145
|
+
case 'recent_auth_required':
|
|
1146
|
+
throw new auth_errors_js_1.RecentAuthRequiredError();
|
|
1147
|
+
case 'recent_mfa_required':
|
|
1148
|
+
throw new auth_errors_js_1.RecentMfaRequiredError();
|
|
1149
|
+
case 'mfa_already_enabled':
|
|
1150
|
+
throw new auth_errors_js_1.MfaAlreadyEnabledError();
|
|
1151
|
+
case 'mfa_enrollment_not_found':
|
|
1152
|
+
throw new auth_errors_js_1.MfaEnrollmentNotFoundError();
|
|
1153
|
+
case 'mfa_not_enabled':
|
|
1154
|
+
throw new auth_errors_js_1.MfaNotEnabledError();
|
|
1009
1155
|
case 'invalid_credentials':
|
|
1010
1156
|
throw new auth_errors_js_1.InvalidCredentialsError();
|
|
1011
1157
|
case 'email_in_use':
|
|
@@ -1030,6 +1176,16 @@ class KoolbaseAuth {
|
|
|
1030
1176
|
case 'contact_not_verified':
|
|
1031
1177
|
case 'email_not_verified':
|
|
1032
1178
|
throw new auth_errors_js_1.ContactNotVerifiedError(msg || undefined);
|
|
1179
|
+
// Sign-in codes. The otp_* codes are shared with phone sign-in; mapped
|
|
1180
|
+
// here, every path that returns them throws the class an app catches.
|
|
1181
|
+
case 'email_code_disabled':
|
|
1182
|
+
throw new auth_errors_js_1.EmailCodeDisabledError();
|
|
1183
|
+
case 'otp_expired':
|
|
1184
|
+
throw new auth_errors_js_1.OtpExpiredError();
|
|
1185
|
+
case 'otp_invalid':
|
|
1186
|
+
throw new auth_errors_js_1.OtpInvalidError();
|
|
1187
|
+
case 'otp_max_attempts':
|
|
1188
|
+
throw new auth_errors_js_1.OtpMaxAttemptsError();
|
|
1033
1189
|
// Registration
|
|
1034
1190
|
case 'signups_disabled':
|
|
1035
1191
|
throw new auth_errors_js_1.SignupsDisabledError(msg || undefined);
|
|
@@ -1116,6 +1272,8 @@ class KoolbaseAuth {
|
|
|
1116
1272
|
const msg = body.error ?? '';
|
|
1117
1273
|
// ─── code-first ───
|
|
1118
1274
|
switch (code) {
|
|
1275
|
+
case 'mfa_required':
|
|
1276
|
+
throw this.mfaRequired(body);
|
|
1119
1277
|
case 'invalid_phone':
|
|
1120
1278
|
throw new auth_errors_js_1.InvalidPhoneNumberError();
|
|
1121
1279
|
case 'otp_expired':
|
|
@@ -195,6 +195,52 @@ export declare class KoolbaseConflictError extends KoolbaseDataError {
|
|
|
195
195
|
field?: string;
|
|
196
196
|
constructor(message?: string, field?: string);
|
|
197
197
|
}
|
|
198
|
+
/**
|
|
199
|
+
* A reference field points at a record that does not exist, is deleted, or
|
|
200
|
+
* lives in another collection — the server responds 400 `reference_invalid`.
|
|
201
|
+
*
|
|
202
|
+
* Checked when the write commits, so it can surface from an insert, an update,
|
|
203
|
+
* an upsert or a batch. In a batch the whole transaction is refused: nothing
|
|
204
|
+
* in it was written.
|
|
205
|
+
*/
|
|
206
|
+
export declare class KoolbaseReferenceInvalidError extends KoolbaseDataError {
|
|
207
|
+
constructor(message?: string);
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* A record could not be deleted because live records still reference it, under
|
|
211
|
+
* a reference declared `on_delete: restrict` — 409 `reference_in_use`.
|
|
212
|
+
*
|
|
213
|
+
* Delete the referencing records first, or in the same batch: the check runs at
|
|
214
|
+
* commit, so one batch may delete a parent and its children in any order.
|
|
215
|
+
*/
|
|
216
|
+
export declare class KoolbaseReferenceInUseError extends KoolbaseDataError {
|
|
217
|
+
constructor(message?: string);
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* A reference could not be declared because existing records already point at
|
|
221
|
+
* records that do not exist — 409 `dangling_references`.
|
|
222
|
+
*
|
|
223
|
+
* `dangling` lists the offending records so they can be repaired; Koolbase
|
|
224
|
+
* never repairs them for you. It is capped at the first 50.
|
|
225
|
+
*/
|
|
226
|
+
export declare class KoolbaseDanglingReferencesError extends KoolbaseDataError {
|
|
227
|
+
dangling: Array<{
|
|
228
|
+
record_id: string;
|
|
229
|
+
value: string;
|
|
230
|
+
}>;
|
|
231
|
+
constructor(message?: string, dangling?: Array<{
|
|
232
|
+
record_id: string;
|
|
233
|
+
value: string;
|
|
234
|
+
}>);
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* A collection could not be deleted because another collection has a reference
|
|
238
|
+
* field pointing at it — 409 `collection_referenced`. Remove that reference
|
|
239
|
+
* first.
|
|
240
|
+
*/
|
|
241
|
+
export declare class KoolbaseCollectionReferencedError extends KoolbaseDataError {
|
|
242
|
+
constructor(message?: string);
|
|
243
|
+
}
|
|
198
244
|
/**
|
|
199
245
|
* Thrown when the requested record or collection does not exist — the server
|
|
200
246
|
* responds with 404 and code `not_found` / `record_not_found` /
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.KoolbaseVectorDimensionMismatchError = exports.KoolbaseRateLimitError = exports.KoolbasePermissionError = exports.KoolbaseInsufficientAuthorityError = exports.KoolbaseValidationError = exports.KoolbaseNotFoundError = exports.KoolbaseConflictError = exports.KoolbaseConstraintNotFoundError = exports.KoolbaseConstraintExistsError = exports.KoolbaseAmbiguousMatchError = exports.KoolbaseDuplicateValuesError = exports.KoolbaseBatchFailedError = exports.KoolbaseIdempotencyKeyReusedError = exports.KoolbaseRevisionMismatchError = exports.KoolbaseProviderInvalidError = exports.KoolbaseProviderNotConfiguredError = exports.KoolbaseInvalidEmbeddingConfigError = exports.KoolbaseFieldNotAutoEmbedError = exports.KoolbaseVectorFieldExistsError = exports.KoolbaseStateConflictError = exports.KoolbaseNoChangesError = exports.KoolbaseInvalidBodyError = exports.KoolbaseProjectInvalidError = exports.KoolbaseInvitationInvalidError = exports.KoolbaseSlugTakenError = exports.KoolbaseSeedError = exports.KoolbaseDataError = void 0;
|
|
3
|
+
exports.KoolbaseVectorDimensionMismatchError = exports.KoolbaseRateLimitError = exports.KoolbasePermissionError = exports.KoolbaseInsufficientAuthorityError = exports.KoolbaseValidationError = exports.KoolbaseNotFoundError = exports.KoolbaseCollectionReferencedError = exports.KoolbaseDanglingReferencesError = exports.KoolbaseReferenceInUseError = exports.KoolbaseReferenceInvalidError = exports.KoolbaseConflictError = exports.KoolbaseConstraintNotFoundError = exports.KoolbaseConstraintExistsError = exports.KoolbaseAmbiguousMatchError = exports.KoolbaseDuplicateValuesError = exports.KoolbaseBatchFailedError = exports.KoolbaseIdempotencyKeyReusedError = exports.KoolbaseRevisionMismatchError = exports.KoolbaseProviderInvalidError = exports.KoolbaseProviderNotConfiguredError = exports.KoolbaseInvalidEmbeddingConfigError = exports.KoolbaseFieldNotAutoEmbedError = exports.KoolbaseVectorFieldExistsError = exports.KoolbaseStateConflictError = exports.KoolbaseNoChangesError = exports.KoolbaseInvalidBodyError = exports.KoolbaseProjectInvalidError = exports.KoolbaseInvitationInvalidError = exports.KoolbaseSlugTakenError = exports.KoolbaseSeedError = exports.KoolbaseDataError = void 0;
|
|
4
4
|
exports.koolbaseDataError = koolbaseDataError;
|
|
5
5
|
const errors_js_1 = require("./errors.js");
|
|
6
6
|
/**
|
|
@@ -297,6 +297,66 @@ class KoolbaseConflictError extends KoolbaseDataError {
|
|
|
297
297
|
}
|
|
298
298
|
}
|
|
299
299
|
exports.KoolbaseConflictError = KoolbaseConflictError;
|
|
300
|
+
/**
|
|
301
|
+
* A reference field points at a record that does not exist, is deleted, or
|
|
302
|
+
* lives in another collection — the server responds 400 `reference_invalid`.
|
|
303
|
+
*
|
|
304
|
+
* Checked when the write commits, so it can surface from an insert, an update,
|
|
305
|
+
* an upsert or a batch. In a batch the whole transaction is refused: nothing
|
|
306
|
+
* in it was written.
|
|
307
|
+
*/
|
|
308
|
+
class KoolbaseReferenceInvalidError extends KoolbaseDataError {
|
|
309
|
+
constructor(message) {
|
|
310
|
+
super(message ?? 'A reference points at a record that does not exist', 'reference_invalid');
|
|
311
|
+
this.name = 'KoolbaseReferenceInvalidError';
|
|
312
|
+
Object.setPrototypeOf(this, KoolbaseReferenceInvalidError.prototype);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
exports.KoolbaseReferenceInvalidError = KoolbaseReferenceInvalidError;
|
|
316
|
+
/**
|
|
317
|
+
* A record could not be deleted because live records still reference it, under
|
|
318
|
+
* a reference declared `on_delete: restrict` — 409 `reference_in_use`.
|
|
319
|
+
*
|
|
320
|
+
* Delete the referencing records first, or in the same batch: the check runs at
|
|
321
|
+
* commit, so one batch may delete a parent and its children in any order.
|
|
322
|
+
*/
|
|
323
|
+
class KoolbaseReferenceInUseError extends KoolbaseDataError {
|
|
324
|
+
constructor(message) {
|
|
325
|
+
super(message ?? 'This record is still referenced by other records', 'reference_in_use');
|
|
326
|
+
this.name = 'KoolbaseReferenceInUseError';
|
|
327
|
+
Object.setPrototypeOf(this, KoolbaseReferenceInUseError.prototype);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
exports.KoolbaseReferenceInUseError = KoolbaseReferenceInUseError;
|
|
331
|
+
/**
|
|
332
|
+
* A reference could not be declared because existing records already point at
|
|
333
|
+
* records that do not exist — 409 `dangling_references`.
|
|
334
|
+
*
|
|
335
|
+
* `dangling` lists the offending records so they can be repaired; Koolbase
|
|
336
|
+
* never repairs them for you. It is capped at the first 50.
|
|
337
|
+
*/
|
|
338
|
+
class KoolbaseDanglingReferencesError extends KoolbaseDataError {
|
|
339
|
+
constructor(message, dangling) {
|
|
340
|
+
super(message ?? 'Existing records point at records that do not exist', 'dangling_references');
|
|
341
|
+
this.dangling = dangling ?? [];
|
|
342
|
+
this.name = 'KoolbaseDanglingReferencesError';
|
|
343
|
+
Object.setPrototypeOf(this, KoolbaseDanglingReferencesError.prototype);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
exports.KoolbaseDanglingReferencesError = KoolbaseDanglingReferencesError;
|
|
347
|
+
/**
|
|
348
|
+
* A collection could not be deleted because another collection has a reference
|
|
349
|
+
* field pointing at it — 409 `collection_referenced`. Remove that reference
|
|
350
|
+
* first.
|
|
351
|
+
*/
|
|
352
|
+
class KoolbaseCollectionReferencedError extends KoolbaseDataError {
|
|
353
|
+
constructor(message) {
|
|
354
|
+
super(message ?? 'Another collection references this one', 'collection_referenced');
|
|
355
|
+
this.name = 'KoolbaseCollectionReferencedError';
|
|
356
|
+
Object.setPrototypeOf(this, KoolbaseCollectionReferencedError.prototype);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
exports.KoolbaseCollectionReferencedError = KoolbaseCollectionReferencedError;
|
|
300
360
|
/**
|
|
301
361
|
* Thrown when the requested record or collection does not exist — the server
|
|
302
362
|
* responds with 404 and code `not_found` / `record_not_found` /
|
|
@@ -427,6 +487,16 @@ function koolbaseDataError(status, body, fallbackMessage = 'Request failed') {
|
|
|
427
487
|
switch (code) {
|
|
428
488
|
case 'unique_violation':
|
|
429
489
|
return attach(new KoolbaseConflictError(message, field));
|
|
490
|
+
case 'reference_invalid':
|
|
491
|
+
return attach(new KoolbaseReferenceInvalidError(message));
|
|
492
|
+
case 'reference_in_use':
|
|
493
|
+
return attach(new KoolbaseReferenceInUseError(message));
|
|
494
|
+
case 'dangling_references': {
|
|
495
|
+
const d = (body?.details ?? {});
|
|
496
|
+
return attach(new KoolbaseDanglingReferencesError(message, d.dangling));
|
|
497
|
+
}
|
|
498
|
+
case 'collection_referenced':
|
|
499
|
+
return attach(new KoolbaseCollectionReferencedError(message));
|
|
430
500
|
case 'plan_limit_reached': {
|
|
431
501
|
const d = (body?.details ?? {});
|
|
432
502
|
return new errors_js_1.KoolbasePlanLimitError(message, d.resource, d.limit, d.plan);
|