@koolbase/react-native 9.0.0 → 9.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/README.md +135 -16
- package/dist/analytics.d.ts +0 -2
- package/dist/analytics.js +2 -26
- package/dist/auth-errors.d.ts +2 -2
- package/dist/auth-errors.js +3 -3
- package/dist/auth.d.ts +14 -0
- package/dist/auth.js +16 -0
- package/dist/cache-store.d.ts +42 -3
- package/dist/cache-store.js +62 -1
- package/dist/conflict.d.ts +80 -0
- package/dist/conflict.js +84 -0
- package/dist/database-errors.d.ts +9 -3
- package/dist/database-errors.js +42 -15
- package/dist/database.d.ts +91 -1
- package/dist/database.js +438 -94
- package/dist/device-id.d.ts +1 -0
- package/dist/device-id.js +60 -0
- package/dist/errors.d.ts +64 -0
- package/dist/errors.js +85 -0
- package/dist/function-errors.d.ts +51 -0
- package/dist/function-errors.js +103 -0
- package/dist/functions.d.ts +8 -1
- package/dist/functions.js +18 -5
- package/dist/index.d.ts +5 -1
- package/dist/index.js +22 -12
- package/dist/messaging.d.ts +0 -7
- package/dist/messaging.js +0 -22
- package/dist/offline-state.d.ts +97 -0
- package/dist/offline-state.js +200 -0
- package/dist/pending-write.d.ts +47 -0
- package/dist/pending-write.js +22 -0
- package/dist/realtime.d.ts +26 -1
- package/dist/realtime.js +50 -3
- package/dist/record.js +3 -0
- package/dist/storage-errors.d.ts +2 -2
- package/dist/storage-errors.js +7 -3
- package/dist/storage.d.ts +15 -1
- package/dist/storage.js +23 -10
- package/dist/sync-engine.d.ts +15 -1
- package/dist/sync-engine.js +226 -22
- package/dist/types.d.ts +18 -1
- package/package.json +13 -7
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { KoolbaseError } from './errors';
|
|
1
2
|
/**
|
|
2
3
|
* Base class for errors surfaced by the Koolbase data layer (database reads
|
|
3
4
|
* and writes). Every data error carries a `message` and, when the server
|
|
@@ -7,8 +8,13 @@
|
|
|
7
8
|
* Catch this to handle any data-layer failure generically, or catch a
|
|
8
9
|
* specific subclass to branch on the kind of failure.
|
|
9
10
|
*/
|
|
10
|
-
export declare class KoolbaseDataError extends
|
|
11
|
-
|
|
11
|
+
export declare class KoolbaseDataError extends KoolbaseError {
|
|
12
|
+
/**
|
|
13
|
+
* Structured payload from the server's error body, when it sent one — e.g. a
|
|
14
|
+
* revision_mismatch 409 carries {expected_revision, current_revision,
|
|
15
|
+
* record}. Attached by the factory; absent when the body had none.
|
|
16
|
+
*/
|
|
17
|
+
details?: Record<string, unknown>;
|
|
12
18
|
constructor(message: string, code?: string);
|
|
13
19
|
}
|
|
14
20
|
/**
|
|
@@ -92,4 +98,4 @@ export declare class KoolbaseVectorDimensionMismatchError extends KoolbaseDataEr
|
|
|
92
98
|
* preferring the server's stable `code` and falling back to the HTTP status
|
|
93
99
|
* for older or uncoded responses. Always returns an error to throw.
|
|
94
100
|
*/
|
|
95
|
-
export declare function koolbaseDataError(status: number, body: any, fallbackMessage?: string):
|
|
101
|
+
export declare function koolbaseDataError(status: number, body: any, fallbackMessage?: string): KoolbaseError;
|
package/dist/database-errors.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.KoolbaseVectorDimensionMismatchError = exports.KoolbaseRateLimitError = exports.KoolbasePermissionError = exports.KoolbaseValidationError = exports.KoolbaseNotFoundError = exports.KoolbaseConflictError = exports.KoolbaseDataError = void 0;
|
|
4
4
|
exports.koolbaseDataError = koolbaseDataError;
|
|
5
|
+
const errors_1 = require("./errors");
|
|
5
6
|
/**
|
|
6
7
|
* Base class for errors surfaced by the Koolbase data layer (database reads
|
|
7
8
|
* and writes). Every data error carries a `message` and, when the server
|
|
@@ -11,10 +12,9 @@ exports.koolbaseDataError = koolbaseDataError;
|
|
|
11
12
|
* Catch this to handle any data-layer failure generically, or catch a
|
|
12
13
|
* specific subclass to branch on the kind of failure.
|
|
13
14
|
*/
|
|
14
|
-
class KoolbaseDataError extends
|
|
15
|
+
class KoolbaseDataError extends errors_1.KoolbaseError {
|
|
15
16
|
constructor(message, code) {
|
|
16
|
-
super(message);
|
|
17
|
-
this.code = code;
|
|
17
|
+
super(message, code);
|
|
18
18
|
this.name = 'KoolbaseDataError';
|
|
19
19
|
Object.setPrototypeOf(this, KoolbaseDataError.prototype);
|
|
20
20
|
}
|
|
@@ -135,39 +135,66 @@ function koolbaseDataError(status, body, fallbackMessage = 'Request failed') {
|
|
|
135
135
|
const code = body?.code;
|
|
136
136
|
const message = body?.error ?? fallbackMessage;
|
|
137
137
|
const field = body?.details?.field;
|
|
138
|
+
const attach = (err) => {
|
|
139
|
+
// The body's structured details ride along on data errors — a
|
|
140
|
+
// revision_mismatch 409 carries the current revision and record, and
|
|
141
|
+
// discarding them here is how a refused conflict-resolution became
|
|
142
|
+
// permanently unresolvable: the information arrived and died in this file.
|
|
143
|
+
if (err instanceof KoolbaseDataError && body?.details) {
|
|
144
|
+
err.details = body.details;
|
|
145
|
+
}
|
|
146
|
+
return err;
|
|
147
|
+
};
|
|
148
|
+
// Status-first for auth: a 401 means the credentials were not accepted,
|
|
149
|
+
// whatever code the body claims. Trusting a mislabelled body here bypasses
|
|
150
|
+
// session-clearing and strands the app signed-in with dead credentials.
|
|
151
|
+
if (status === 401) {
|
|
152
|
+
return new errors_1.KoolbaseUnauthenticatedError(message);
|
|
153
|
+
}
|
|
138
154
|
// ─── code-first ───
|
|
139
155
|
switch (code) {
|
|
140
156
|
case 'unique_violation':
|
|
141
|
-
return new KoolbaseConflictError(message, field);
|
|
157
|
+
return attach(new KoolbaseConflictError(message, field));
|
|
142
158
|
case 'not_found':
|
|
143
159
|
case 'record_not_found':
|
|
144
160
|
case 'collection_not_found':
|
|
145
161
|
case 'vector_not_found':
|
|
146
162
|
case 'vector_field_not_found':
|
|
147
|
-
return new KoolbaseNotFoundError(message);
|
|
163
|
+
return attach(new KoolbaseNotFoundError(message));
|
|
164
|
+
case 'unauthenticated':
|
|
165
|
+
case 'session_expired':
|
|
166
|
+
case 'invalid_token':
|
|
167
|
+
return attach(new errors_1.KoolbaseUnauthenticatedError(message));
|
|
148
168
|
case 'permission_denied':
|
|
149
|
-
return new KoolbasePermissionError(message);
|
|
169
|
+
return attach(new KoolbasePermissionError(message));
|
|
150
170
|
case 'rate_limit':
|
|
151
|
-
return new KoolbaseRateLimitError(message);
|
|
171
|
+
return attach(new KoolbaseRateLimitError(message));
|
|
152
172
|
case 'validation_error':
|
|
153
173
|
case 'vector_collection_mismatch':
|
|
154
174
|
case 'unsupported_dimension':
|
|
155
|
-
return new KoolbaseValidationError(message);
|
|
175
|
+
return attach(new KoolbaseValidationError(message));
|
|
156
176
|
case 'vector_dimension_mismatch':
|
|
157
|
-
return new KoolbaseVectorDimensionMismatchError(message);
|
|
177
|
+
return attach(new KoolbaseVectorDimensionMismatchError(message));
|
|
158
178
|
}
|
|
159
179
|
// ─── status fallback (pre-code servers) ───
|
|
160
180
|
switch (status) {
|
|
161
181
|
case 409:
|
|
162
|
-
return new KoolbaseConflictError(message);
|
|
182
|
+
return attach(new KoolbaseConflictError(message));
|
|
163
183
|
case 404:
|
|
164
|
-
return new KoolbaseNotFoundError(message);
|
|
184
|
+
return attach(new KoolbaseNotFoundError(message));
|
|
185
|
+
case 401:
|
|
186
|
+
// The status carries the meaning: every 401 from this server reports the
|
|
187
|
+
// same code, so it cannot say whether the session expired, the key was
|
|
188
|
+
// revoked, or the header was malformed. Safe to treat uniformly because a
|
|
189
|
+
// permission failure is 403 — a 401 means the credentials were not
|
|
190
|
+
// accepted, not that this caller may not proceed.
|
|
191
|
+
return attach(new errors_1.KoolbaseUnauthenticatedError(message));
|
|
165
192
|
case 403:
|
|
166
|
-
return new KoolbasePermissionError(message);
|
|
193
|
+
return attach(new KoolbasePermissionError(message));
|
|
167
194
|
case 429:
|
|
168
|
-
return new KoolbaseRateLimitError(message);
|
|
195
|
+
return attach(new KoolbaseRateLimitError(message));
|
|
169
196
|
case 400:
|
|
170
|
-
return new KoolbaseValidationError(message);
|
|
197
|
+
return attach(new KoolbaseValidationError(message));
|
|
171
198
|
}
|
|
172
|
-
return new KoolbaseDataError(message, code);
|
|
199
|
+
return attach(new KoolbaseDataError(message, code));
|
|
173
200
|
}
|
package/dist/database.d.ts
CHANGED
|
@@ -1,13 +1,50 @@
|
|
|
1
|
+
import { KoolbaseConflict } from './conflict';
|
|
2
|
+
import { PendingWrite } from './pending-write';
|
|
1
3
|
import { KoolbaseConfig, KoolbaseRecord, QueryOptions, QueryResult, UpsertResult, BatchOp, BatchResult, KoolbaseVector, SemanticSearchResult, SearchMode } from './types';
|
|
2
4
|
export declare class KoolbaseDatabase {
|
|
3
5
|
private config;
|
|
4
6
|
private getUserId;
|
|
5
7
|
private getToken;
|
|
8
|
+
/**
|
|
9
|
+
* Called when the server rejects the caller's credentials.
|
|
10
|
+
*
|
|
11
|
+
* A session stops working for the whole SDK at once, so it is cleared before
|
|
12
|
+
* the error reaches the caller — otherwise the app keeps believing it is
|
|
13
|
+
* signed in and every subsequent call fails the same way, with no path back
|
|
14
|
+
* to login.
|
|
15
|
+
*/
|
|
16
|
+
private onSessionExpired?;
|
|
6
17
|
private syncEngine;
|
|
7
|
-
constructor(config: KoolbaseConfig, getUserId: () => string | null, getToken: () => Promise<string | null>);
|
|
18
|
+
constructor(config: KoolbaseConfig, getUserId: () => string | null, getToken: () => Promise<string | null>, onSessionExpired?: () => Promise<void>);
|
|
8
19
|
private buildHeaders;
|
|
9
20
|
private request;
|
|
21
|
+
/**
|
|
22
|
+
* Like [request], but returns the status alongside the body.
|
|
23
|
+
*
|
|
24
|
+
* Several operations need it — upsert distinguishes create from update by a
|
|
25
|
+
* 201, batch reports per-operation outcomes — and needing it was why they
|
|
26
|
+
* hand-rolled their own fetch, each mapping errors slightly differently and
|
|
27
|
+
* none of them clearing a rejected session. One path, two shapes of result.
|
|
28
|
+
*/
|
|
29
|
+
private requestWithStatus;
|
|
10
30
|
private runQuery;
|
|
31
|
+
/**
|
|
32
|
+
* Query records, cache-first (stale-while-revalidate).
|
|
33
|
+
*
|
|
34
|
+
* A cache hit is returned immediately with `isFromCache: true`, and a
|
|
35
|
+
* background refresh updates the cache for the next call — so a repeat
|
|
36
|
+
* query converges on the server's state one call behind it. Only a cache
|
|
37
|
+
* miss awaits the network (`isFromCache: false`).
|
|
38
|
+
*
|
|
39
|
+
* Two consequences worth designing for: results can be one refresh stale,
|
|
40
|
+
* even online — re-query if you need convergence after a known write; and
|
|
41
|
+
* background refresh failures are swallowed by design (the cached result
|
|
42
|
+
* has already been returned), so a dead network looks identical to a slow
|
|
43
|
+
* refresh. Check `isFromCache` when the difference matters.
|
|
44
|
+
*
|
|
45
|
+
* The cache is per-user and persisted; it doubles as the offline baseline
|
|
46
|
+
* store for `update`/`delete`.
|
|
47
|
+
*/
|
|
11
48
|
query(collection: string, options?: QueryOptions): Promise<QueryResult>;
|
|
12
49
|
/**
|
|
13
50
|
* Insert a new record into a collection.
|
|
@@ -75,6 +112,46 @@ export declare class KoolbaseDatabase {
|
|
|
75
112
|
*/
|
|
76
113
|
batch(operations: BatchOp[]): Promise<BatchResult[]>;
|
|
77
114
|
get(recordId: string): Promise<KoolbaseRecord>;
|
|
115
|
+
/**
|
|
116
|
+
* Writes that could not be applied, waiting for a decision.
|
|
117
|
+
*
|
|
118
|
+
* Held rather than discarded, and surviving restarts. An app that never reads
|
|
119
|
+
* these accumulates them invisibly, with the changes they hold never applied —
|
|
120
|
+
* so if you support offline editing, surface them somewhere.
|
|
121
|
+
*/
|
|
122
|
+
/**
|
|
123
|
+
* Changes made offline, waiting to be sent. Oldest first.
|
|
124
|
+
*
|
|
125
|
+
* For sync indicators ("3 changes waiting") and for warning a user who is
|
|
126
|
+
* about to log out with unsynced edits — see [PendingWrite] for why that
|
|
127
|
+
* moment matters. Snapshot, not a live handle; per-user.
|
|
128
|
+
*/
|
|
129
|
+
pendingWrites(): Promise<PendingWrite[]>;
|
|
130
|
+
conflicts(): Promise<KoolbaseConflict[]>;
|
|
131
|
+
/**
|
|
132
|
+
* Resolves by id, reloading the stored conflict first.
|
|
133
|
+
*
|
|
134
|
+
* A conflict object handed to a UI can sit there while someone decides, and a
|
|
135
|
+
* sync pass may resolve it or another write supersede it meanwhile. Acting on
|
|
136
|
+
* values captured when the object was built would write against a state that
|
|
137
|
+
* no longer exists.
|
|
138
|
+
*/
|
|
139
|
+
private readonly conflictResolver;
|
|
140
|
+
/**
|
|
141
|
+
* Per-user state demands a user. Signed out, "no answer" must not be
|
|
142
|
+
* disguised as "empty" — tonight's fake-zero: the display read the anonymous
|
|
143
|
+
* bucket while a signed-in user's writes sat unseen in theirs.
|
|
144
|
+
*/
|
|
145
|
+
private requireUserId;
|
|
146
|
+
private requireConflict;
|
|
147
|
+
private dropConflict;
|
|
148
|
+
/**
|
|
149
|
+
* Issues the resolving write, conditional on the revision the refusal
|
|
150
|
+
* reported, and clears the conflict only once the server accepts it.
|
|
151
|
+
*
|
|
152
|
+
* Clearing first would lose the change if the write then failed.
|
|
153
|
+
*/
|
|
154
|
+
private applyResolution;
|
|
78
155
|
/**
|
|
79
156
|
* Update a record's fields by id.
|
|
80
157
|
*
|
|
@@ -88,6 +165,19 @@ export declare class KoolbaseDatabase {
|
|
|
88
165
|
* optimistic record is returned so the UI can re-render the new fields
|
|
89
166
|
* immediately.
|
|
90
167
|
*/
|
|
168
|
+
/**
|
|
169
|
+
* The record's state as the SDK last knew it, for composing an offline
|
|
170
|
+
* mutation against.
|
|
171
|
+
*
|
|
172
|
+
* Two sources, in order. A record created offline is not in the cache as a
|
|
173
|
+
* server record, but its queued insert holds the state a later edit builds on
|
|
174
|
+
* — insert-then-correct is the ordinary offline sequence. Otherwise the cached
|
|
175
|
+
* copy, with the revision it was read at.
|
|
176
|
+
*
|
|
177
|
+
* Null when neither exists: never seen on this device, or a queued delete has
|
|
178
|
+
* already removed it locally.
|
|
179
|
+
*/
|
|
180
|
+
private resolveBaseline;
|
|
91
181
|
update(recordId: string, data: Record<string, unknown>): Promise<KoolbaseRecord>;
|
|
92
182
|
delete(recordId: string): Promise<void>;
|
|
93
183
|
/**
|