@koolbase/core 11.2.0 → 11.3.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.
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.KoolbaseStorageMetadataInvalidError = exports.KoolbaseStorageMimeTypeError = exports.KoolbaseStorageFileTooLargeError = exports.KoolbaseStorageQuotaError = exports.KoolbaseCapBelowUsageError = exports.KoolbaseUploadExpiredError = exports.KoolbaseStoragePermissionError = exports.KoolbaseStorageValidationError = exports.KoolbaseStorageNotFoundError = exports.KoolbaseStorageConflictError = exports.KoolbaseStorageError = void 0;
3
+ exports.KoolbaseStorageMetadataInvalidError = exports.KoolbaseStorageMimeTypeError = exports.KoolbaseStorageFileTooLargeError = exports.KoolbaseStorageQuotaError = exports.KoolbaseCapBelowUsageError = exports.KoolbaseUploadExpiredError = exports.KoolbaseUploadURLFailedError = exports.KoolbaseStoragePermissionError = exports.KoolbaseStorageValidationError = exports.KoolbaseStorageNotFoundError = exports.KoolbaseStorageConflictError = exports.KoolbaseStorageError = void 0;
4
4
  exports.koolbaseStorageError = koolbaseStorageError;
5
5
  exports.koolbaseStorageErrorFromResponse = koolbaseStorageErrorFromResponse;
6
6
  const errors_js_1 = require("./errors.js");
@@ -114,6 +114,21 @@ exports.KoolbaseStoragePermissionError = KoolbaseStoragePermissionError;
114
114
  * failure: presign again and send the same bytes. Worth catching rather than
115
115
  * showing "upload failed" to someone whose file was fine.
116
116
  */
117
+ /**
118
+ * Minting a presigned upload URL failed. The message carries the underlying
119
+ * reason — a misconfigured bucket, or the object store refusing.
120
+ *
121
+ * Not the user's doing, and not a retry they can fix: distinct from
122
+ * KoolbaseUploadExpiredError, which is a retry that will work.
123
+ */
124
+ class KoolbaseUploadURLFailedError extends KoolbaseStorageError {
125
+ constructor(message) {
126
+ super(message ?? 'Could not create an upload URL', 'upload_url_failed');
127
+ this.name = 'KoolbaseUploadURLFailedError';
128
+ Object.setPrototypeOf(this, KoolbaseUploadURLFailedError.prototype);
129
+ }
130
+ }
131
+ exports.KoolbaseUploadURLFailedError = KoolbaseUploadURLFailedError;
117
132
  class KoolbaseUploadExpiredError extends KoolbaseStorageError {
118
133
  constructor(message) {
119
134
  super(message ?? 'This upload is past the confirmation window — please re-upload', 'upload_expired');
@@ -235,6 +250,10 @@ function koolbaseStorageError(status, body, fallbackMessage = 'Storage request f
235
250
  switch (code) {
236
251
  case 'path_conflict':
237
252
  return new KoolbaseStorageConflictError(message, body?.path);
253
+ case 'plan_limit_reached': {
254
+ const d = (body?.details ?? {});
255
+ return new errors_js_1.KoolbasePlanLimitError(message, d.resource, d.limit, d.plan);
256
+ }
238
257
  case 'quota_exceeded':
239
258
  return new KoolbaseStorageQuotaError(message);
240
259
  case 'upload_expired':
@@ -247,6 +266,8 @@ function koolbaseStorageError(status, body, fallbackMessage = 'Storage request f
247
266
  return new KoolbaseStorageMimeTypeError(message);
248
267
  case 'metadata_invalid':
249
268
  return new KoolbaseStorageMetadataInvalidError(message, body?.detail);
269
+ case 'upload_url_failed':
270
+ return new KoolbaseUploadURLFailedError(message);
250
271
  }
251
272
  // ─── status fallback (pre-code servers or uncoded paths) ───
252
273
  switch (status) {
@@ -217,6 +217,29 @@ export declare class LastCredentialError extends KoolbaseAuthError {
217
217
  export declare class HideRequiresVerificationError extends KoolbaseAuthError {
218
218
  constructor(message?: string);
219
219
  }
220
+ /**
221
+ * The API key's scope is below what the operation requires.
222
+ *
223
+ * Scopes rank read < write < admin. Not a credential problem — the key is
224
+ * valid, and a different key or a dashboard session is needed. Worth its own
225
+ * type so an app does not tell someone to sign in again when signing in will
226
+ * not help.
227
+ */
228
+ export declare class InsufficientScopeError extends KoolbaseAuthError {
229
+ constructor(message?: string);
230
+ }
231
+ /** The provider is not connected to this account. */
232
+ export declare class IdentityNotFoundError extends KoolbaseAuthError {
233
+ constructor(message?: string);
234
+ }
235
+ /**
236
+ * Connecting a Google or Apple identity that another account already holds.
237
+ * Distinct from AccountExistsError, which is about the email; this is about
238
+ * the provider identity itself.
239
+ */
240
+ export declare class ProviderIdentityAlreadyLinkedError extends KoolbaseAuthError {
241
+ constructor(message?: string);
242
+ }
220
243
  export declare class MalformedSessionResponseError extends KoolbaseAuthError {
221
244
  constructor(missing: string);
222
245
  }
@@ -370,6 +370,41 @@ export class HideRequiresVerificationError extends KoolbaseAuthError {
370
370
  Object.setPrototypeOf(this, HideRequiresVerificationError.prototype);
371
371
  }
372
372
  }
373
+ /**
374
+ * The API key's scope is below what the operation requires.
375
+ *
376
+ * Scopes rank read < write < admin. Not a credential problem — the key is
377
+ * valid, and a different key or a dashboard session is needed. Worth its own
378
+ * type so an app does not tell someone to sign in again when signing in will
379
+ * not help.
380
+ */
381
+ export class InsufficientScopeError extends KoolbaseAuthError {
382
+ constructor(message) {
383
+ super(message ?? "This key's scope does not permit this operation", 'insufficient_scope');
384
+ this.name = 'InsufficientScopeError';
385
+ Object.setPrototypeOf(this, InsufficientScopeError.prototype);
386
+ }
387
+ }
388
+ /** The provider is not connected to this account. */
389
+ export class IdentityNotFoundError extends KoolbaseAuthError {
390
+ constructor(message) {
391
+ super(message ?? 'That provider is not connected to your account', 'identity_not_found');
392
+ this.name = 'IdentityNotFoundError';
393
+ Object.setPrototypeOf(this, IdentityNotFoundError.prototype);
394
+ }
395
+ }
396
+ /**
397
+ * Connecting a Google or Apple identity that another account already holds.
398
+ * Distinct from AccountExistsError, which is about the email; this is about
399
+ * the provider identity itself.
400
+ */
401
+ export class ProviderIdentityAlreadyLinkedError extends KoolbaseAuthError {
402
+ constructor(message) {
403
+ super(message ?? 'That provider identity is already linked to another account', 'provider_identity_already_linked');
404
+ this.name = 'ProviderIdentityAlreadyLinkedError';
405
+ Object.setPrototypeOf(this, ProviderIdentityAlreadyLinkedError.prototype);
406
+ }
407
+ }
373
408
  export class MalformedSessionResponseError extends KoolbaseAuthError {
374
409
  constructor(missing) {
375
410
  super(`The server returned a session without ${missing}. This is a protocol error, not a credential problem.`, 'malformed_session_response');
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, MalformedSessionResponseError, AccountExistsError, ContactNotVerifiedError, CurrentPasswordIncorrectError, HideRequiresVerificationError, InsufficientAuthorityError, LastCredentialError, OAuthOnlyAccountError, SessionRequiredError, SignupsDisabledError, TokenAlreadyUsedError, TokenExpiredError, UnsupportedOAuthProviderError, RateLimitError, VerificationResendCooldownError, VerificationResendDailyCapError, 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, IdentityNotFoundError, InsufficientScopeError, MalformedSessionResponseError, ProviderIdentityAlreadyLinkedError, AccountExistsError, ContactNotVerifiedError, CurrentPasswordIncorrectError, HideRequiresVerificationError, InsufficientAuthorityError, LastCredentialError, OAuthOnlyAccountError, SessionRequiredError, SignupsDisabledError, TokenAlreadyUsedError, TokenExpiredError, UnsupportedOAuthProviderError, RateLimitError, VerificationResendCooldownError, VerificationResendDailyCapError, SessionExpiredError, SmsConfigMissingError, 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 {
@@ -195,9 +195,16 @@ export class KoolbaseAuth {
195
195
  return RestoreResult.Restored;
196
196
  }
197
197
  catch (e) {
198
- if (e instanceof SessionExpiredError ||
199
- e instanceof TokenRevokedError ||
200
- e instanceof InvalidCredentialsError) {
198
+ // Only a refresh the server refused clears the stored session, and
199
+ // only because the refresh token is the last credential there is — once
200
+ // it is rejected there is nothing left to try.
201
+ //
202
+ // InvalidCredentialsError used to be in this list. It means "these
203
+ // credentials are wrong", which during a restore points at the project
204
+ // key or the request rather than the user's session — and deleting the
205
+ // refresh token on that reading signs someone out with no way back.
206
+ // Nothing reaches here with it today; it stays out so nothing does.
207
+ if (e instanceof SessionExpiredError) {
201
208
  await this.clearSessionInternal();
202
209
  return RestoreResult.Expired;
203
210
  }
@@ -788,8 +795,6 @@ export class KoolbaseAuth {
788
795
  case 'invalid_refresh_token':
789
796
  // Refresh token rejected — the session is unrecoverable; re-login.
790
797
  throw new SessionExpiredError();
791
- case 'token_revoked':
792
- throw new TokenRevokedError();
793
798
  case 'invalid_unlock_token':
794
799
  throw new UnlockTokenInvalidError();
795
800
  case 'rate_limit':
@@ -828,6 +833,12 @@ export class KoolbaseAuth {
828
833
  throw new OAuthOnlyAccountError(msg || undefined);
829
834
  case 'unsupported_oauth_provider':
830
835
  throw new UnsupportedOAuthProviderError(msg || undefined);
836
+ case 'identity_not_found':
837
+ throw new IdentityNotFoundError(msg || undefined);
838
+ case 'provider_identity_already_linked':
839
+ throw new ProviderIdentityAlreadyLinkedError(msg || undefined);
840
+ case 'insufficient_scope':
841
+ throw new InsufficientScopeError(msg || undefined);
831
842
  // Authority
832
843
  case 'session_required':
833
844
  throw new SessionRequiredError(msg || undefined);
@@ -860,11 +871,6 @@ export class KoolbaseAuth {
860
871
  if (msg.includes('invalid or expired unlock token')) {
861
872
  throw new UnlockTokenInvalidError();
862
873
  }
863
- if (msg.includes('session revoked') ||
864
- msg.includes('token revoked') ||
865
- msg.includes('session has been revoked')) {
866
- throw new TokenRevokedError();
867
- }
868
874
  throw new KoolbaseAuthError(msg || `Request failed: ${res.status}`, code || `http_${res.status}`);
869
875
  }
870
876
  /**
@@ -49,6 +49,137 @@ export declare class KoolbaseDataError extends KoolbaseError {
49
49
  * nobody asked to change. Narrow the filter, or add a unique constraint over
50
50
  * the fields you are matching on so the ambiguity cannot arise.
51
51
  */
52
+ /**
53
+ * The record changed between reading it and writing it.
54
+ *
55
+ * Optimistic concurrency: a write carrying a revision is refused when the
56
+ * server has moved on, rather than overwriting whatever happened in between.
57
+ * The refusal carries the server's current record and both revisions, so
58
+ * resolving needs no second fetch — and cannot race one.
59
+ *
60
+ * Distinct from KoolbaseConflict, which models a queued OFFLINE write and
61
+ * carries a baseline as well, because a change composed hours ago needs its
62
+ * original context to be resolvable. Here the caller still has their data in
63
+ * hand.
64
+ *
65
+ * Until 11.3.0 this arrived as a generic data error and the details had to be
66
+ * dug out of an untyped bag — the information the server went to the trouble
67
+ * of attaching, unreachable in practice.
68
+ */
69
+ /** A vector field with that name already exists on the collection. */
70
+ /**
71
+ * A seed or import operation was refused. The code says which stage:
72
+ * invalid_seed_file (the file itself, with a "problems" list in details),
73
+ * seed_key_not_unique (the key does not identify rows uniquely),
74
+ * seed_needs_decision (conflicts need a choice before proceeding), or
75
+ * seed_conflicts_require_force (overwriting would discard the target's
76
+ * version of rows that changed on both sides — details carry the rows).
77
+ *
78
+ * One class with the code distinguishing them, rather than four: these are
79
+ * dashboard and CLI operations, and a caller handling one handles them the
80
+ * same way — show the reason and let a human decide.
81
+ */
82
+ export declare class KoolbaseSeedError extends KoolbaseDataError {
83
+ constructor(message: string, code: string);
84
+ }
85
+ /** A project slug that another project already holds. */
86
+ export declare class KoolbaseSlugTakenError extends KoolbaseDataError {
87
+ constructor(message?: string);
88
+ }
89
+ /** An invitation that has been revoked or has expired. */
90
+ export declare class KoolbaseInvitationInvalidError extends KoolbaseDataError {
91
+ constructor(message?: string);
92
+ }
93
+ /** The project id in the request is not valid. */
94
+ export declare class KoolbaseProjectInvalidError extends KoolbaseDataError {
95
+ constructor(message?: string);
96
+ }
97
+ /** The request body could not be decoded. */
98
+ export declare class KoolbaseInvalidBodyError extends KoolbaseDataError {
99
+ constructor(message?: string);
100
+ }
101
+ /**
102
+ * The request asked for no change — an update with nothing to update.
103
+ */
104
+ export declare class KoolbaseNoChangesError extends KoolbaseDataError {
105
+ constructor(message?: string);
106
+ }
107
+ /**
108
+ * Something already exists, or something is in the wrong state, where the
109
+ * server did not say more than that.
110
+ *
111
+ * Carries whichever generic code arrived — conflict, duplicate,
112
+ * state_conflict — rather than four classes for codes that differ only in
113
+ * spelling. A caller who needs to branch finely is being underserved by the
114
+ * server, not by this.
115
+ */
116
+ export declare class KoolbaseStateConflictError extends KoolbaseDataError {
117
+ constructor(message: string, code: string);
118
+ }
119
+ export declare class KoolbaseVectorFieldExistsError extends KoolbaseDataError {
120
+ constructor(message?: string);
121
+ }
122
+ /**
123
+ * A backfill was asked for on a field that embeds nothing automatically.
124
+ * Set provider, model and source_field on the field first.
125
+ */
126
+ export declare class KoolbaseFieldNotAutoEmbedError extends KoolbaseDataError {
127
+ constructor(message?: string);
128
+ }
129
+ /**
130
+ * Embedding config is partial. Provider, model and source_field are set
131
+ * together or cleared together — half a configuration is refused rather than
132
+ * half-applied, which would embed against a model nobody chose.
133
+ */
134
+ export declare class KoolbaseInvalidEmbeddingConfigError extends KoolbaseDataError {
135
+ constructor(message?: string);
136
+ }
137
+ /**
138
+ * The project has no embedding provider configured. Embedding runs on the
139
+ * project's own Gemini or OpenAI key.
140
+ */
141
+ export declare class KoolbaseProviderNotConfiguredError extends KoolbaseDataError {
142
+ constructor(message?: string);
143
+ }
144
+ /** The configured provider's credentials were rejected by the provider. */
145
+ export declare class KoolbaseProviderInvalidError extends KoolbaseDataError {
146
+ constructor(message?: string);
147
+ }
148
+ export declare class KoolbaseRevisionMismatchError extends KoolbaseDataError {
149
+ readonly expectedRevision?: number | undefined;
150
+ readonly currentRevision?: number | undefined;
151
+ /** The record as the server holds it now. */
152
+ readonly current?: Record<string, unknown> | undefined;
153
+ constructor(message?: string, expectedRevision?: number | undefined, currentRevision?: number | undefined,
154
+ /** The record as the server holds it now. */
155
+ current?: Record<string, unknown> | undefined);
156
+ }
157
+ /**
158
+ * The same idempotency key sent with different data.
159
+ *
160
+ * Refused rather than replayed: the two requests do not agree, so neither
161
+ * answer is safe. Usually a key reused by accident across two operations.
162
+ */
163
+ export declare class KoolbaseIdempotencyKeyReusedError extends KoolbaseDataError {
164
+ /**
165
+ * Carries its code: the database package calls this idempotency_key_reused
166
+ * and fiscal calls it idempotency_conflict, and an error reporting a code
167
+ * the server did not send is a small lie that apps branching on e.code act
168
+ * on.
169
+ */
170
+ constructor(message?: string, code?: string);
171
+ }
172
+ /** A batch write failed for a reason the server did not classify further. */
173
+ export declare class KoolbaseBatchFailedError extends KoolbaseDataError {
174
+ constructor(message?: string);
175
+ }
176
+ /**
177
+ * Creating a unique constraint over data that already breaks it. details
178
+ * carry the offending values, so they can be shown rather than hunted for.
179
+ */
180
+ export declare class KoolbaseDuplicateValuesError extends KoolbaseDataError {
181
+ constructor(message?: string);
182
+ }
52
183
  export declare class KoolbaseAmbiguousMatchError extends KoolbaseDataError {
53
184
  constructor(message?: string);
54
185
  }
@@ -1,4 +1,4 @@
1
- import { KoolbaseError, KoolbaseUnauthenticatedError } from './errors.js';
1
+ import { KoolbaseError, KoolbasePlanLimitError, KoolbaseUnauthenticatedError } from './errors.js';
2
2
  /**
3
3
  * Base class for errors surfaced by the Koolbase data layer (database reads
4
4
  * and writes). Every data error carries a `message` and, when the server
@@ -47,6 +47,200 @@ export class KoolbaseDataError extends KoolbaseError {
47
47
  * nobody asked to change. Narrow the filter, or add a unique constraint over
48
48
  * the fields you are matching on so the ambiguity cannot arise.
49
49
  */
50
+ /**
51
+ * The record changed between reading it and writing it.
52
+ *
53
+ * Optimistic concurrency: a write carrying a revision is refused when the
54
+ * server has moved on, rather than overwriting whatever happened in between.
55
+ * The refusal carries the server's current record and both revisions, so
56
+ * resolving needs no second fetch — and cannot race one.
57
+ *
58
+ * Distinct from KoolbaseConflict, which models a queued OFFLINE write and
59
+ * carries a baseline as well, because a change composed hours ago needs its
60
+ * original context to be resolvable. Here the caller still has their data in
61
+ * hand.
62
+ *
63
+ * Until 11.3.0 this arrived as a generic data error and the details had to be
64
+ * dug out of an untyped bag — the information the server went to the trouble
65
+ * of attaching, unreachable in practice.
66
+ */
67
+ /** A vector field with that name already exists on the collection. */
68
+ /**
69
+ * A seed or import operation was refused. The code says which stage:
70
+ * invalid_seed_file (the file itself, with a "problems" list in details),
71
+ * seed_key_not_unique (the key does not identify rows uniquely),
72
+ * seed_needs_decision (conflicts need a choice before proceeding), or
73
+ * seed_conflicts_require_force (overwriting would discard the target's
74
+ * version of rows that changed on both sides — details carry the rows).
75
+ *
76
+ * One class with the code distinguishing them, rather than four: these are
77
+ * dashboard and CLI operations, and a caller handling one handles them the
78
+ * same way — show the reason and let a human decide.
79
+ */
80
+ export class KoolbaseSeedError extends KoolbaseDataError {
81
+ constructor(message, code) {
82
+ super(message, code);
83
+ this.name = 'KoolbaseSeedError';
84
+ Object.setPrototypeOf(this, KoolbaseSeedError.prototype);
85
+ }
86
+ }
87
+ /** A project slug that another project already holds. */
88
+ export class KoolbaseSlugTakenError extends KoolbaseDataError {
89
+ constructor(message) {
90
+ super(message ?? 'A project with this slug already exists', 'slug_taken');
91
+ this.name = 'KoolbaseSlugTakenError';
92
+ Object.setPrototypeOf(this, KoolbaseSlugTakenError.prototype);
93
+ }
94
+ }
95
+ /** An invitation that has been revoked or has expired. */
96
+ export class KoolbaseInvitationInvalidError extends KoolbaseDataError {
97
+ constructor(message) {
98
+ super(message ?? 'This invitation has been revoked or expired', 'invitation_invalid');
99
+ this.name = 'KoolbaseInvitationInvalidError';
100
+ Object.setPrototypeOf(this, KoolbaseInvitationInvalidError.prototype);
101
+ }
102
+ }
103
+ /** The project id in the request is not valid. */
104
+ export class KoolbaseProjectInvalidError extends KoolbaseDataError {
105
+ constructor(message) {
106
+ super(message ?? 'Invalid project id', 'project_invalid');
107
+ this.name = 'KoolbaseProjectInvalidError';
108
+ Object.setPrototypeOf(this, KoolbaseProjectInvalidError.prototype);
109
+ }
110
+ }
111
+ /** The request body could not be decoded. */
112
+ export class KoolbaseInvalidBodyError extends KoolbaseDataError {
113
+ constructor(message) {
114
+ super(message ?? 'Could not decode the request body', 'invalid_body');
115
+ this.name = 'KoolbaseInvalidBodyError';
116
+ Object.setPrototypeOf(this, KoolbaseInvalidBodyError.prototype);
117
+ }
118
+ }
119
+ /**
120
+ * The request asked for no change — an update with nothing to update.
121
+ */
122
+ export class KoolbaseNoChangesError extends KoolbaseDataError {
123
+ constructor(message) {
124
+ super(message ?? 'The request contains no changes', 'no_changes');
125
+ this.name = 'KoolbaseNoChangesError';
126
+ Object.setPrototypeOf(this, KoolbaseNoChangesError.prototype);
127
+ }
128
+ }
129
+ /**
130
+ * Something already exists, or something is in the wrong state, where the
131
+ * server did not say more than that.
132
+ *
133
+ * Carries whichever generic code arrived — conflict, duplicate,
134
+ * state_conflict — rather than four classes for codes that differ only in
135
+ * spelling. A caller who needs to branch finely is being underserved by the
136
+ * server, not by this.
137
+ */
138
+ export class KoolbaseStateConflictError extends KoolbaseDataError {
139
+ constructor(message, code) {
140
+ super(message, code);
141
+ this.name = 'KoolbaseStateConflictError';
142
+ Object.setPrototypeOf(this, KoolbaseStateConflictError.prototype);
143
+ }
144
+ }
145
+ export class KoolbaseVectorFieldExistsError extends KoolbaseDataError {
146
+ constructor(message) {
147
+ super(message ?? 'A vector field with that name already exists on this collection', 'vector_field_exists');
148
+ this.name = 'KoolbaseVectorFieldExistsError';
149
+ Object.setPrototypeOf(this, KoolbaseVectorFieldExistsError.prototype);
150
+ }
151
+ }
152
+ /**
153
+ * A backfill was asked for on a field that embeds nothing automatically.
154
+ * Set provider, model and source_field on the field first.
155
+ */
156
+ export class KoolbaseFieldNotAutoEmbedError extends KoolbaseDataError {
157
+ constructor(message) {
158
+ super(message ?? 'This vector field has no auto-embedding config; set provider, model and source_field first', 'field_not_auto_embed');
159
+ this.name = 'KoolbaseFieldNotAutoEmbedError';
160
+ Object.setPrototypeOf(this, KoolbaseFieldNotAutoEmbedError.prototype);
161
+ }
162
+ }
163
+ /**
164
+ * Embedding config is partial. Provider, model and source_field are set
165
+ * together or cleared together — half a configuration is refused rather than
166
+ * half-applied, which would embed against a model nobody chose.
167
+ */
168
+ export class KoolbaseInvalidEmbeddingConfigError extends KoolbaseDataError {
169
+ constructor(message) {
170
+ super(message ?? 'Embedding config requires provider, model and source_field together, or all cleared', 'invalid_embedding_config');
171
+ this.name = 'KoolbaseInvalidEmbeddingConfigError';
172
+ Object.setPrototypeOf(this, KoolbaseInvalidEmbeddingConfigError.prototype);
173
+ }
174
+ }
175
+ /**
176
+ * The project has no embedding provider configured. Embedding runs on the
177
+ * project's own Gemini or OpenAI key.
178
+ */
179
+ export class KoolbaseProviderNotConfiguredError extends KoolbaseDataError {
180
+ constructor(message) {
181
+ super(message ?? 'No embedding provider is configured for this project', 'provider_not_configured');
182
+ this.name = 'KoolbaseProviderNotConfiguredError';
183
+ Object.setPrototypeOf(this, KoolbaseProviderNotConfiguredError.prototype);
184
+ }
185
+ }
186
+ /** The configured provider's credentials were rejected by the provider. */
187
+ export class KoolbaseProviderInvalidError extends KoolbaseDataError {
188
+ constructor(message) {
189
+ super(message ?? 'The embedding provider credentials are not valid', 'provider_invalid');
190
+ this.name = 'KoolbaseProviderInvalidError';
191
+ Object.setPrototypeOf(this, KoolbaseProviderInvalidError.prototype);
192
+ }
193
+ }
194
+ export class KoolbaseRevisionMismatchError extends KoolbaseDataError {
195
+ constructor(message, expectedRevision, currentRevision,
196
+ /** The record as the server holds it now. */
197
+ current) {
198
+ super(message ?? 'The record has changed since you read it', 'revision_mismatch');
199
+ this.expectedRevision = expectedRevision;
200
+ this.currentRevision = currentRevision;
201
+ this.current = current;
202
+ this.name = 'KoolbaseRevisionMismatchError';
203
+ Object.setPrototypeOf(this, KoolbaseRevisionMismatchError.prototype);
204
+ }
205
+ }
206
+ /**
207
+ * The same idempotency key sent with different data.
208
+ *
209
+ * Refused rather than replayed: the two requests do not agree, so neither
210
+ * answer is safe. Usually a key reused by accident across two operations.
211
+ */
212
+ export class KoolbaseIdempotencyKeyReusedError extends KoolbaseDataError {
213
+ /**
214
+ * Carries its code: the database package calls this idempotency_key_reused
215
+ * and fiscal calls it idempotency_conflict, and an error reporting a code
216
+ * the server did not send is a small lie that apps branching on e.code act
217
+ * on.
218
+ */
219
+ constructor(message, code = 'idempotency_key_reused') {
220
+ super(message ?? 'Idempotency key reused with different data', code);
221
+ this.name = 'KoolbaseIdempotencyKeyReusedError';
222
+ Object.setPrototypeOf(this, KoolbaseIdempotencyKeyReusedError.prototype);
223
+ }
224
+ }
225
+ /** A batch write failed for a reason the server did not classify further. */
226
+ export class KoolbaseBatchFailedError extends KoolbaseDataError {
227
+ constructor(message) {
228
+ super(message ?? 'The batch write failed', 'batch_failed');
229
+ this.name = 'KoolbaseBatchFailedError';
230
+ Object.setPrototypeOf(this, KoolbaseBatchFailedError.prototype);
231
+ }
232
+ }
233
+ /**
234
+ * Creating a unique constraint over data that already breaks it. details
235
+ * carry the offending values, so they can be shown rather than hunted for.
236
+ */
237
+ export class KoolbaseDuplicateValuesError extends KoolbaseDataError {
238
+ constructor(message) {
239
+ super(message ?? 'The collection has duplicate values for these fields', 'duplicate_values');
240
+ this.name = 'KoolbaseDuplicateValuesError';
241
+ Object.setPrototypeOf(this, KoolbaseDuplicateValuesError.prototype);
242
+ }
243
+ }
50
244
  export class KoolbaseAmbiguousMatchError extends KoolbaseDataError {
51
245
  constructor(message) {
52
246
  super(message ?? 'Upsert match resolved to more than one record', 'ambiguous_match');
@@ -202,6 +396,55 @@ export function koolbaseDataError(status, body, fallbackMessage = 'Request faile
202
396
  switch (code) {
203
397
  case 'unique_violation':
204
398
  return attach(new KoolbaseConflictError(message, field));
399
+ case 'plan_limit_reached': {
400
+ const d = (body?.details ?? {});
401
+ return new KoolbasePlanLimitError(message, d.resource, d.limit, d.plan);
402
+ }
403
+ case 'invalid_seed_file':
404
+ case 'seed_key_not_unique':
405
+ case 'seed_needs_decision':
406
+ case 'seed_conflicts_require_force':
407
+ return attach(new KoolbaseSeedError(message, code));
408
+ case 'slug_taken':
409
+ return attach(new KoolbaseSlugTakenError(message));
410
+ case 'invitation_invalid':
411
+ return attach(new KoolbaseInvitationInvalidError(message));
412
+ case 'project_invalid':
413
+ return attach(new KoolbaseProjectInvalidError(message));
414
+ case 'invalid_body':
415
+ return attach(new KoolbaseInvalidBodyError(message));
416
+ case 'no_changes':
417
+ return attach(new KoolbaseNoChangesError(message));
418
+ case 'conflict':
419
+ case 'duplicate':
420
+ case 'state_conflict':
421
+ return attach(new KoolbaseStateConflictError(message, code));
422
+ case 'vector_field_exists':
423
+ return attach(new KoolbaseVectorFieldExistsError(message));
424
+ case 'field_not_auto_embed':
425
+ return attach(new KoolbaseFieldNotAutoEmbedError(message));
426
+ case 'invalid_embedding_config':
427
+ return attach(new KoolbaseInvalidEmbeddingConfigError(message));
428
+ case 'provider_not_configured':
429
+ return attach(new KoolbaseProviderNotConfiguredError(message));
430
+ case 'provider_invalid':
431
+ return attach(new KoolbaseProviderInvalidError(message));
432
+ case 'revision_mismatch': {
433
+ // The typed fields come off details, which the server attaches for
434
+ // exactly this. attach() still puts the whole bag on the error, so
435
+ // nothing is lost for a caller reading it directly.
436
+ const d = (body?.details ?? {});
437
+ return attach(new KoolbaseRevisionMismatchError(message, d.expected_revision, d.current_revision, d.record));
438
+ }
439
+ // Two codes, one situation — the database and fiscal packages name it
440
+ // differently and a caller should not have to know which spoke.
441
+ case 'idempotency_key_reused':
442
+ case 'idempotency_conflict':
443
+ return attach(new KoolbaseIdempotencyKeyReusedError(message, code));
444
+ case 'batch_failed':
445
+ return attach(new KoolbaseBatchFailedError(message));
446
+ case 'duplicate_values':
447
+ return attach(new KoolbaseDuplicateValuesError(message));
205
448
  case 'ambiguous_match':
206
449
  return attach(new KoolbaseAmbiguousMatchError(message));
207
450
  case 'constraint_exists':
@@ -217,7 +460,6 @@ export function koolbaseDataError(status, body, fallbackMessage = 'Request faile
217
460
  case 'vector_field_not_found':
218
461
  return attach(new KoolbaseNotFoundError(message, code));
219
462
  case 'unauthenticated':
220
- case 'session_expired':
221
463
  case 'invalid_token':
222
464
  return attach(new KoolbaseUnauthenticatedError(message));
223
465
  case 'permission_denied':
@@ -59,6 +59,20 @@ export declare class KoolbaseUnauthenticatedError extends KoolbaseError {
59
59
  * updates are conflict-safe and some quietly are not, which is a worse guarantee
60
60
  * than a clear refusal.
61
61
  */
62
+ /**
63
+ * The project's plan does not allow this — a 402 carrying which resource, the
64
+ * limit, and the plan.
65
+ *
66
+ * Shared rather than per-domain: creating a collection, uploading an object
67
+ * and deploying a function can all hit it, and an app showing an upgrade
68
+ * prompt wants one type to catch.
69
+ */
70
+ export declare class KoolbasePlanLimitError extends KoolbaseError {
71
+ readonly resource?: string | undefined;
72
+ readonly limit?: number | undefined;
73
+ readonly plan?: string | undefined;
74
+ constructor(message?: string, resource?: string | undefined, limit?: number | undefined, plan?: string | undefined);
75
+ }
62
76
  export declare class KoolbaseOfflineBaselineUnavailableError extends KoolbaseError {
63
77
  constructor(message: string);
64
78
  }
@@ -70,6 +70,24 @@ export class KoolbaseUnauthenticatedError extends KoolbaseError {
70
70
  * updates are conflict-safe and some quietly are not, which is a worse guarantee
71
71
  * than a clear refusal.
72
72
  */
73
+ /**
74
+ * The project's plan does not allow this — a 402 carrying which resource, the
75
+ * limit, and the plan.
76
+ *
77
+ * Shared rather than per-domain: creating a collection, uploading an object
78
+ * and deploying a function can all hit it, and an app showing an upgrade
79
+ * prompt wants one type to catch.
80
+ */
81
+ export class KoolbasePlanLimitError extends KoolbaseError {
82
+ constructor(message, resource, limit, plan) {
83
+ super(message ?? 'This exceeds your plan limit', 'plan_limit_reached');
84
+ this.resource = resource;
85
+ this.limit = limit;
86
+ this.plan = plan;
87
+ this.name = 'KoolbasePlanLimitError';
88
+ Object.setPrototypeOf(this, KoolbasePlanLimitError.prototype);
89
+ }
90
+ }
73
91
  export class KoolbaseOfflineBaselineUnavailableError extends KoolbaseError {
74
92
  constructor(message) {
75
93
  super(message, 'offline_baseline_unavailable');
@@ -84,6 +84,16 @@ export declare class KoolbaseStoragePermissionError extends KoolbaseStorageError
84
84
  * failure: presign again and send the same bytes. Worth catching rather than
85
85
  * showing "upload failed" to someone whose file was fine.
86
86
  */
87
+ /**
88
+ * Minting a presigned upload URL failed. The message carries the underlying
89
+ * reason — a misconfigured bucket, or the object store refusing.
90
+ *
91
+ * Not the user's doing, and not a retry they can fix: distinct from
92
+ * KoolbaseUploadExpiredError, which is a retry that will work.
93
+ */
94
+ export declare class KoolbaseUploadURLFailedError extends KoolbaseStorageError {
95
+ constructor(message?: string);
96
+ }
87
97
  export declare class KoolbaseUploadExpiredError extends KoolbaseStorageError {
88
98
  constructor(message?: string);
89
99
  }