@koolbase/react-native 9.2.0 → 10.0.1
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/CHANGELOG.md +1348 -0
- package/README.md +403 -568
- package/dist/{auth-storage.d.ts → cjs/auth-storage.d.ts} +1 -1
- package/dist/cjs/index.d.ts +19 -0
- package/dist/cjs/index.js +125 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/platform.d.ts +2 -0
- package/dist/cjs/platform.js +43 -0
- package/dist/esm/auth-storage.d.ts +26 -0
- package/dist/esm/auth-storage.js +100 -0
- package/dist/esm/index.d.ts +19 -0
- package/dist/esm/index.js +106 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/platform.d.ts +2 -0
- package/dist/esm/platform.js +37 -0
- package/package.json +30 -30
- package/dist/analytics.d.ts +0 -24
- package/dist/analytics.js +0 -114
- package/dist/apple-auth.d.ts +0 -22
- package/dist/apple-auth.js +0 -74
- package/dist/auth-errors.d.ts +0 -117
- package/dist/auth-errors.js +0 -250
- package/dist/auth.d.ts +0 -213
- package/dist/auth.js +0 -810
- package/dist/cache-store.d.ts +0 -50
- package/dist/cache-store.js +0 -197
- package/dist/code-push.d.ts +0 -59
- package/dist/code-push.js +0 -255
- package/dist/conflict.d.ts +0 -80
- package/dist/conflict.js +0 -84
- package/dist/database-errors.d.ts +0 -101
- package/dist/database-errors.js +0 -200
- package/dist/database.d.ts +0 -298
- package/dist/database.js +0 -852
- package/dist/device-id.d.ts +0 -1
- package/dist/device-id.js +0 -60
- package/dist/device-metadata.d.ts +0 -36
- package/dist/device-metadata.js +0 -102
- package/dist/errors.d.ts +0 -64
- package/dist/errors.js +0 -85
- package/dist/flags.d.ts +0 -15
- package/dist/flags.js +0 -76
- package/dist/function-errors.d.ts +0 -51
- package/dist/function-errors.js +0 -103
- package/dist/functions.d.ts +0 -15
- package/dist/functions.js +0 -83
- package/dist/index.d.ts +0 -49
- package/dist/index.js +0 -204
- package/dist/logic-engine.d.ts +0 -17
- package/dist/logic-engine.js +0 -193
- package/dist/messaging.d.ts +0 -13
- package/dist/messaging.js +0 -36
- package/dist/offline-state.d.ts +0 -97
- package/dist/offline-state.js +0 -200
- package/dist/pending-write.d.ts +0 -47
- package/dist/pending-write.js +0 -22
- package/dist/realtime.d.ts +0 -44
- package/dist/realtime.js +0 -195
- package/dist/record.d.ts +0 -2
- package/dist/record.js +0 -23
- package/dist/storage-errors.d.ts +0 -163
- package/dist/storage-errors.js +0 -253
- package/dist/storage.d.ts +0 -198
- package/dist/storage.js +0 -451
- package/dist/sync-engine.d.ts +0 -30
- package/dist/sync-engine.js +0 -290
- package/dist/types.d.ts +0 -487
- package/dist/types.js +0 -40
- /package/dist/{auth-storage.js → cjs/auth-storage.js} +0 -0
package/dist/conflict.js
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.KoolbaseConflict = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* A queued offline write that could not be applied, waiting for a decision.
|
|
6
|
-
*
|
|
7
|
-
* Not an error to dismiss and not a write to retry: retrying cannot help, and
|
|
8
|
-
* discarding it would lose a change the user believes is saved. It waits, and
|
|
9
|
-
* keeps waiting across restarts, until the application decides.
|
|
10
|
-
*
|
|
11
|
-
* Only the application can decide. Whether a later edit should win depends on
|
|
12
|
-
* what the data means, and a platform that chooses for everyone is wrong for
|
|
13
|
-
* someone.
|
|
14
|
-
*/
|
|
15
|
-
class KoolbaseConflict {
|
|
16
|
-
constructor(id, reason, operation, collection, recordId,
|
|
17
|
-
/** The change the user made, still unapplied. */
|
|
18
|
-
local,
|
|
19
|
-
/** The record as it was when the change was composed, where that is known. */
|
|
20
|
-
baseline,
|
|
21
|
-
/**
|
|
22
|
-
* The record as the server held it when the write was refused, captured with
|
|
23
|
-
* the refusal so deciding needs no fetch and cannot race one.
|
|
24
|
-
*
|
|
25
|
-
* Undefined when the reason is `baseline_unavailable` — nothing was ever
|
|
26
|
-
* sent, so the server never answered.
|
|
27
|
-
*/
|
|
28
|
-
server, baseRevision, serverRevision, createdAt, resolver) {
|
|
29
|
-
this.id = id;
|
|
30
|
-
this.reason = reason;
|
|
31
|
-
this.operation = operation;
|
|
32
|
-
this.collection = collection;
|
|
33
|
-
this.recordId = recordId;
|
|
34
|
-
this.local = local;
|
|
35
|
-
this.baseline = baseline;
|
|
36
|
-
this.server = server;
|
|
37
|
-
this.baseRevision = baseRevision;
|
|
38
|
-
this.serverRevision = serverRevision;
|
|
39
|
-
this.createdAt = createdAt;
|
|
40
|
-
this.resolver = resolver;
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Fields where the user's change and the server's version disagree.
|
|
44
|
-
*
|
|
45
|
-
* Only the fields the change touches: a record accumulates values the write
|
|
46
|
-
* never asserted, and listing those would bury the real disagreement. Empty
|
|
47
|
-
* when there is no server version to compare against.
|
|
48
|
-
*/
|
|
49
|
-
get divergentFields() {
|
|
50
|
-
if (!this.local)
|
|
51
|
-
return [];
|
|
52
|
-
if (!this.server)
|
|
53
|
-
return Object.keys(this.local);
|
|
54
|
-
return Object.keys(this.local).filter((k) => JSON.stringify(this.server[k]) !== JSON.stringify(this.local[k]));
|
|
55
|
-
}
|
|
56
|
-
/** How long this has been waiting. Metadata, not a deletion rule. */
|
|
57
|
-
get ageMs() {
|
|
58
|
-
return Date.now() - new Date(this.createdAt).getTime();
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Reapplies the user's change to the record as it stands now.
|
|
62
|
-
*
|
|
63
|
-
* An explicit decision to overwrite the server's version of the fields that
|
|
64
|
-
* disagree. Conditional where a revision is known, so a record that moved
|
|
65
|
-
* again while someone was deciding produces a new conflict rather than an
|
|
66
|
-
* unnoticed overwrite.
|
|
67
|
-
*/
|
|
68
|
-
resolveWithLocal() {
|
|
69
|
-
return this.resolver.resolveWithLocal(this.id);
|
|
70
|
-
}
|
|
71
|
-
/** Keeps the server's version and discards the user's change, as a decision. */
|
|
72
|
-
resolveWithServer() {
|
|
73
|
-
return this.resolver.resolveWithServer(this.id);
|
|
74
|
-
}
|
|
75
|
-
/** Applies something the application composed from both versions. */
|
|
76
|
-
resolveWithMerge(data) {
|
|
77
|
-
return this.resolver.resolveWithMerge(this.id, data);
|
|
78
|
-
}
|
|
79
|
-
/** Drops the change without claiming either version won. */
|
|
80
|
-
abandon() {
|
|
81
|
-
return this.resolver.abandon(this.id);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
exports.KoolbaseConflict = KoolbaseConflict;
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { KoolbaseError } from './errors';
|
|
2
|
-
/**
|
|
3
|
-
* Base class for errors surfaced by the Koolbase data layer (database reads
|
|
4
|
-
* and writes). Every data error carries a `message` and, when the server
|
|
5
|
-
* provides one, its stable `code` (e.g. `not_found`, `validation_error`,
|
|
6
|
-
* `unique_violation`).
|
|
7
|
-
*
|
|
8
|
-
* Catch this to handle any data-layer failure generically, or catch a
|
|
9
|
-
* specific subclass to branch on the kind of failure.
|
|
10
|
-
*/
|
|
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>;
|
|
18
|
-
constructor(message: string, code?: string);
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Thrown when a write is rejected because the value would violate a
|
|
22
|
-
* collection's unique constraint — the server responds with 409 Conflict.
|
|
23
|
-
* Catch it to handle duplicates, e.g. an email or username already in use.
|
|
24
|
-
*
|
|
25
|
-
* `field` names the field that collided, when the server reports it
|
|
26
|
-
* (`details.field`) — useful when a collection has more than one unique
|
|
27
|
-
* constraint and you need to know which value clashed.
|
|
28
|
-
*
|
|
29
|
-
* Surfaced by `insert`, `update`, and `upsert` whenever the server is
|
|
30
|
-
* reachable and rejects the write with a 409. These writes are online-first:
|
|
31
|
-
* a server-side conflict throws immediately. Only a genuine network failure
|
|
32
|
-
* falls back to the offline queue, where a conflict that surfaces at sync
|
|
33
|
-
* time is handled by the sync engine rather than thrown here.
|
|
34
|
-
*
|
|
35
|
-
* @example
|
|
36
|
-
* try {
|
|
37
|
-
* await koolbase.db.upsert('users', { email }, { name });
|
|
38
|
-
* } catch (e) {
|
|
39
|
-
* if (e instanceof KoolbaseConflictError) {
|
|
40
|
-
* showError(`That ${e.field ?? 'value'} is already registered.`);
|
|
41
|
-
* }
|
|
42
|
-
* }
|
|
43
|
-
*/
|
|
44
|
-
export declare class KoolbaseConflictError extends KoolbaseDataError {
|
|
45
|
-
field?: string;
|
|
46
|
-
constructor(message?: string, field?: string);
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Thrown when the requested record or collection does not exist — the server
|
|
50
|
-
* responds with 404 and code `not_found` / `record_not_found` /
|
|
51
|
-
* `collection_not_found`.
|
|
52
|
-
*/
|
|
53
|
-
export declare class KoolbaseNotFoundError extends KoolbaseDataError {
|
|
54
|
-
constructor(message?: string);
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Thrown when the request is rejected as invalid — the server responds with
|
|
58
|
-
* 400 and code `validation_error`.
|
|
59
|
-
*/
|
|
60
|
-
export declare class KoolbaseValidationError extends KoolbaseDataError {
|
|
61
|
-
constructor(message?: string);
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Thrown when the caller is authenticated but not allowed to perform the
|
|
65
|
-
* operation — the server responds with 403 and code `permission_denied`
|
|
66
|
-
* (typically a collection access rule rejecting the read/write).
|
|
67
|
-
*/
|
|
68
|
-
export declare class KoolbasePermissionError extends KoolbaseDataError {
|
|
69
|
-
constructor(message?: string);
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Thrown when the server is rate-limiting the caller — 429 with code
|
|
73
|
-
* `rate_limit`. Back off and retry after a short delay.
|
|
74
|
-
*/
|
|
75
|
-
export declare class KoolbaseRateLimitError extends KoolbaseDataError {
|
|
76
|
-
constructor(message?: string);
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Thrown when the supplied vector's length does not match the dimension
|
|
80
|
-
* declared on the collection's vector field — the server responds with
|
|
81
|
-
* 400 and code `vector_dimension_mismatch`. The message includes both
|
|
82
|
-
* the expected and actual dimensions so you can surface a precise error.
|
|
83
|
-
*
|
|
84
|
-
* @example
|
|
85
|
-
* try {
|
|
86
|
-
* await koolbase.db.setVector(id, 'embedding', [0.1, 0.2]); // 2 dims
|
|
87
|
-
* } catch (e) {
|
|
88
|
-
* if (e instanceof KoolbaseVectorDimensionMismatchError) {
|
|
89
|
-
* showError(e.message); // "expected 1536, got 2"
|
|
90
|
-
* }
|
|
91
|
-
* }
|
|
92
|
-
*/
|
|
93
|
-
export declare class KoolbaseVectorDimensionMismatchError extends KoolbaseDataError {
|
|
94
|
-
constructor(message?: string);
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Maps a non-2xx data-layer response to a typed {@link KoolbaseDataError},
|
|
98
|
-
* preferring the server's stable `code` and falling back to the HTTP status
|
|
99
|
-
* for older or uncoded responses. Always returns an error to throw.
|
|
100
|
-
*/
|
|
101
|
-
export declare function koolbaseDataError(status: number, body: any, fallbackMessage?: string): KoolbaseError;
|
package/dist/database-errors.js
DELETED
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.KoolbaseVectorDimensionMismatchError = exports.KoolbaseRateLimitError = exports.KoolbasePermissionError = exports.KoolbaseValidationError = exports.KoolbaseNotFoundError = exports.KoolbaseConflictError = exports.KoolbaseDataError = void 0;
|
|
4
|
-
exports.koolbaseDataError = koolbaseDataError;
|
|
5
|
-
const errors_1 = require("./errors");
|
|
6
|
-
/**
|
|
7
|
-
* Base class for errors surfaced by the Koolbase data layer (database reads
|
|
8
|
-
* and writes). Every data error carries a `message` and, when the server
|
|
9
|
-
* provides one, its stable `code` (e.g. `not_found`, `validation_error`,
|
|
10
|
-
* `unique_violation`).
|
|
11
|
-
*
|
|
12
|
-
* Catch this to handle any data-layer failure generically, or catch a
|
|
13
|
-
* specific subclass to branch on the kind of failure.
|
|
14
|
-
*/
|
|
15
|
-
class KoolbaseDataError extends errors_1.KoolbaseError {
|
|
16
|
-
constructor(message, code) {
|
|
17
|
-
super(message, code);
|
|
18
|
-
this.name = 'KoolbaseDataError';
|
|
19
|
-
Object.setPrototypeOf(this, KoolbaseDataError.prototype);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
exports.KoolbaseDataError = KoolbaseDataError;
|
|
23
|
-
/**
|
|
24
|
-
* Thrown when a write is rejected because the value would violate a
|
|
25
|
-
* collection's unique constraint — the server responds with 409 Conflict.
|
|
26
|
-
* Catch it to handle duplicates, e.g. an email or username already in use.
|
|
27
|
-
*
|
|
28
|
-
* `field` names the field that collided, when the server reports it
|
|
29
|
-
* (`details.field`) — useful when a collection has more than one unique
|
|
30
|
-
* constraint and you need to know which value clashed.
|
|
31
|
-
*
|
|
32
|
-
* Surfaced by `insert`, `update`, and `upsert` whenever the server is
|
|
33
|
-
* reachable and rejects the write with a 409. These writes are online-first:
|
|
34
|
-
* a server-side conflict throws immediately. Only a genuine network failure
|
|
35
|
-
* falls back to the offline queue, where a conflict that surfaces at sync
|
|
36
|
-
* time is handled by the sync engine rather than thrown here.
|
|
37
|
-
*
|
|
38
|
-
* @example
|
|
39
|
-
* try {
|
|
40
|
-
* await koolbase.db.upsert('users', { email }, { name });
|
|
41
|
-
* } catch (e) {
|
|
42
|
-
* if (e instanceof KoolbaseConflictError) {
|
|
43
|
-
* showError(`That ${e.field ?? 'value'} is already registered.`);
|
|
44
|
-
* }
|
|
45
|
-
* }
|
|
46
|
-
*/
|
|
47
|
-
class KoolbaseConflictError extends KoolbaseDataError {
|
|
48
|
-
constructor(message, field) {
|
|
49
|
-
super(message ?? 'Value violates a unique constraint', 'unique_violation');
|
|
50
|
-
this.field = field;
|
|
51
|
-
this.name = 'KoolbaseConflictError';
|
|
52
|
-
Object.setPrototypeOf(this, KoolbaseConflictError.prototype);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
exports.KoolbaseConflictError = KoolbaseConflictError;
|
|
56
|
-
/**
|
|
57
|
-
* Thrown when the requested record or collection does not exist — the server
|
|
58
|
-
* responds with 404 and code `not_found` / `record_not_found` /
|
|
59
|
-
* `collection_not_found`.
|
|
60
|
-
*/
|
|
61
|
-
class KoolbaseNotFoundError extends KoolbaseDataError {
|
|
62
|
-
constructor(message) {
|
|
63
|
-
super(message ?? 'The requested resource was not found', 'not_found');
|
|
64
|
-
this.name = 'KoolbaseNotFoundError';
|
|
65
|
-
Object.setPrototypeOf(this, KoolbaseNotFoundError.prototype);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
exports.KoolbaseNotFoundError = KoolbaseNotFoundError;
|
|
69
|
-
/**
|
|
70
|
-
* Thrown when the request is rejected as invalid — the server responds with
|
|
71
|
-
* 400 and code `validation_error`.
|
|
72
|
-
*/
|
|
73
|
-
class KoolbaseValidationError extends KoolbaseDataError {
|
|
74
|
-
constructor(message) {
|
|
75
|
-
super(message ?? 'The request was invalid', 'validation_error');
|
|
76
|
-
this.name = 'KoolbaseValidationError';
|
|
77
|
-
Object.setPrototypeOf(this, KoolbaseValidationError.prototype);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
exports.KoolbaseValidationError = KoolbaseValidationError;
|
|
81
|
-
/**
|
|
82
|
-
* Thrown when the caller is authenticated but not allowed to perform the
|
|
83
|
-
* operation — the server responds with 403 and code `permission_denied`
|
|
84
|
-
* (typically a collection access rule rejecting the read/write).
|
|
85
|
-
*/
|
|
86
|
-
class KoolbasePermissionError extends KoolbaseDataError {
|
|
87
|
-
constructor(message) {
|
|
88
|
-
super(message ?? 'You do not have permission to perform this action', 'permission_denied');
|
|
89
|
-
this.name = 'KoolbasePermissionError';
|
|
90
|
-
Object.setPrototypeOf(this, KoolbasePermissionError.prototype);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
exports.KoolbasePermissionError = KoolbasePermissionError;
|
|
94
|
-
/**
|
|
95
|
-
* Thrown when the server is rate-limiting the caller — 429 with code
|
|
96
|
-
* `rate_limit`. Back off and retry after a short delay.
|
|
97
|
-
*/
|
|
98
|
-
class KoolbaseRateLimitError extends KoolbaseDataError {
|
|
99
|
-
constructor(message) {
|
|
100
|
-
super(message ?? 'Too many requests, please slow down', 'rate_limit');
|
|
101
|
-
this.name = 'KoolbaseRateLimitError';
|
|
102
|
-
Object.setPrototypeOf(this, KoolbaseRateLimitError.prototype);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
exports.KoolbaseRateLimitError = KoolbaseRateLimitError;
|
|
106
|
-
/**
|
|
107
|
-
* Thrown when the supplied vector's length does not match the dimension
|
|
108
|
-
* declared on the collection's vector field — the server responds with
|
|
109
|
-
* 400 and code `vector_dimension_mismatch`. The message includes both
|
|
110
|
-
* the expected and actual dimensions so you can surface a precise error.
|
|
111
|
-
*
|
|
112
|
-
* @example
|
|
113
|
-
* try {
|
|
114
|
-
* await koolbase.db.setVector(id, 'embedding', [0.1, 0.2]); // 2 dims
|
|
115
|
-
* } catch (e) {
|
|
116
|
-
* if (e instanceof KoolbaseVectorDimensionMismatchError) {
|
|
117
|
-
* showError(e.message); // "expected 1536, got 2"
|
|
118
|
-
* }
|
|
119
|
-
* }
|
|
120
|
-
*/
|
|
121
|
-
class KoolbaseVectorDimensionMismatchError extends KoolbaseDataError {
|
|
122
|
-
constructor(message) {
|
|
123
|
-
super(message ?? 'Vector dimension does not match field declaration', 'vector_dimension_mismatch');
|
|
124
|
-
this.name = 'KoolbaseVectorDimensionMismatchError';
|
|
125
|
-
Object.setPrototypeOf(this, KoolbaseVectorDimensionMismatchError.prototype);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
exports.KoolbaseVectorDimensionMismatchError = KoolbaseVectorDimensionMismatchError;
|
|
129
|
-
/**
|
|
130
|
-
* Maps a non-2xx data-layer response to a typed {@link KoolbaseDataError},
|
|
131
|
-
* preferring the server's stable `code` and falling back to the HTTP status
|
|
132
|
-
* for older or uncoded responses. Always returns an error to throw.
|
|
133
|
-
*/
|
|
134
|
-
function koolbaseDataError(status, body, fallbackMessage = 'Request failed') {
|
|
135
|
-
const code = body?.code;
|
|
136
|
-
const message = body?.error ?? fallbackMessage;
|
|
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
|
-
}
|
|
154
|
-
// ─── code-first ───
|
|
155
|
-
switch (code) {
|
|
156
|
-
case 'unique_violation':
|
|
157
|
-
return attach(new KoolbaseConflictError(message, field));
|
|
158
|
-
case 'not_found':
|
|
159
|
-
case 'record_not_found':
|
|
160
|
-
case 'collection_not_found':
|
|
161
|
-
case 'vector_not_found':
|
|
162
|
-
case 'vector_field_not_found':
|
|
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));
|
|
168
|
-
case 'permission_denied':
|
|
169
|
-
return attach(new KoolbasePermissionError(message));
|
|
170
|
-
case 'rate_limit':
|
|
171
|
-
return attach(new KoolbaseRateLimitError(message));
|
|
172
|
-
case 'validation_error':
|
|
173
|
-
case 'vector_collection_mismatch':
|
|
174
|
-
case 'unsupported_dimension':
|
|
175
|
-
return attach(new KoolbaseValidationError(message));
|
|
176
|
-
case 'vector_dimension_mismatch':
|
|
177
|
-
return attach(new KoolbaseVectorDimensionMismatchError(message));
|
|
178
|
-
}
|
|
179
|
-
// ─── status fallback (pre-code servers) ───
|
|
180
|
-
switch (status) {
|
|
181
|
-
case 409:
|
|
182
|
-
return attach(new KoolbaseConflictError(message));
|
|
183
|
-
case 404:
|
|
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));
|
|
192
|
-
case 403:
|
|
193
|
-
return attach(new KoolbasePermissionError(message));
|
|
194
|
-
case 429:
|
|
195
|
-
return attach(new KoolbaseRateLimitError(message));
|
|
196
|
-
case 400:
|
|
197
|
-
return attach(new KoolbaseValidationError(message));
|
|
198
|
-
}
|
|
199
|
-
return attach(new KoolbaseDataError(message, code));
|
|
200
|
-
}
|
package/dist/database.d.ts
DELETED
|
@@ -1,298 +0,0 @@
|
|
|
1
|
-
import { KoolbaseConflict } from './conflict';
|
|
2
|
-
import { PendingWrite } from './pending-write';
|
|
3
|
-
import { KoolbaseConfig, KoolbaseRecord, QueryOptions, QueryResult, UpsertResult, BatchOp, BatchResult, KoolbaseVector, SemanticSearchResult, SearchMode } from './types';
|
|
4
|
-
export declare class KoolbaseDatabase {
|
|
5
|
-
private config;
|
|
6
|
-
private getUserId;
|
|
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?;
|
|
17
|
-
private syncEngine;
|
|
18
|
-
constructor(config: KoolbaseConfig, getUserId: () => string | null, getToken: () => Promise<string | null>, onSessionExpired?: () => Promise<void>);
|
|
19
|
-
private buildHeaders;
|
|
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;
|
|
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
|
-
*/
|
|
48
|
-
query(collection: string, options?: QueryOptions): Promise<QueryResult>;
|
|
49
|
-
/**
|
|
50
|
-
* Insert a new record into a collection.
|
|
51
|
-
*
|
|
52
|
-
* Online-first: awaits the server so a server-side rejection (unique
|
|
53
|
-
* violation, validation error, permission denial) surfaces as the typed
|
|
54
|
-
* `KoolbaseDataError` subclass — `insert` now throws `KoolbaseConflictError`
|
|
55
|
-
* with the offending field on a 409, matching `upsert` and `update`.
|
|
56
|
-
*
|
|
57
|
-
* On genuine network failure (server unreachable, timeout) the write is
|
|
58
|
-
* accepted optimistically: saved to the local cache and queued for sync
|
|
59
|
-
* when connectivity returns.
|
|
60
|
-
*/
|
|
61
|
-
insert(collection: string, data: Record<string, unknown>): Promise<KoolbaseRecord>;
|
|
62
|
-
/**
|
|
63
|
-
* Insert a record, or update the existing one matching `match`.
|
|
64
|
-
*
|
|
65
|
-
* The server decides: exactly one match updates it, no match inserts a new
|
|
66
|
-
* record (seeded with the `match` fields), more than one match is an error.
|
|
67
|
-
* Returns the resulting record and a `created` flag (true = inserted, false
|
|
68
|
-
* = updated).
|
|
69
|
-
*
|
|
70
|
-
* Online-only by design. Unlike `insert`, an upsert is NOT queued offline:
|
|
71
|
-
* the insert-vs-update decision needs the server's authoritative view of
|
|
72
|
-
* what already exists, so deferring it could create a duplicate or apply a
|
|
73
|
-
* wrong update on later sync. It throws on network failure instead. A raw
|
|
74
|
-
* fetch is used (not `request`) so the status code is readable: 201 =
|
|
75
|
-
* created, 200 = updated.
|
|
76
|
-
*/
|
|
77
|
-
upsert(collection: string, match: Record<string, unknown>, data: Record<string, unknown>): Promise<UpsertResult>;
|
|
78
|
-
/**
|
|
79
|
-
* Bulk-delete every record in `collection` matching `filters`.
|
|
80
|
-
*
|
|
81
|
-
* The server applies the collection's delete rule (scoping to the caller for
|
|
82
|
-
* owner/scoped rules) and returns the number of records deleted.
|
|
83
|
-
*
|
|
84
|
-
* Online-only by design — like upsert, this is NOT queued offline: a bulk
|
|
85
|
-
* delete needs the server's authoritative view of what matches, so it throws
|
|
86
|
-
* on network failure rather than risk deleting the wrong set on later sync.
|
|
87
|
-
* The collection cache is invalidated on success.
|
|
88
|
-
*/
|
|
89
|
-
deleteWhere(collection: string, filters: Record<string, unknown>): Promise<number>;
|
|
90
|
-
/**
|
|
91
|
-
* Run multiple writes as a single atomic transaction.
|
|
92
|
-
*
|
|
93
|
-
* All `operations` commit together or none are applied — the server runs
|
|
94
|
-
* them in one database transaction and rolls back entirely on any failure.
|
|
95
|
-
* Operations apply in order and may span multiple collections.
|
|
96
|
-
*
|
|
97
|
-
* Online-only by design (like `upsert` and `deleteWhere`): atomicity needs
|
|
98
|
-
* the server's authoritative view, so a batch is never queued offline — it
|
|
99
|
-
* throws on network failure. A server-side rejection throws a
|
|
100
|
-
* `KoolbaseDataException` whose message identifies which operation failed;
|
|
101
|
-
* nothing was persisted.
|
|
102
|
-
*
|
|
103
|
-
* Returns one `BatchResult` per operation, in order.
|
|
104
|
-
*
|
|
105
|
-
* @example
|
|
106
|
-
* const results = await Koolbase.db.batch([
|
|
107
|
-
* BatchOp.insert('orders', { total: 50 }),
|
|
108
|
-
* BatchOp.update(inventoryId, { stock: 9 }),
|
|
109
|
-
* BatchOp.upsert('counters', { match: { name: 'orders' }, data: { value: 1 } }),
|
|
110
|
-
* BatchOp.delete(cartItemId),
|
|
111
|
-
* ]);
|
|
112
|
-
*/
|
|
113
|
-
batch(operations: BatchOp[]): Promise<BatchResult[]>;
|
|
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;
|
|
155
|
-
/**
|
|
156
|
-
* Update a record's fields by id.
|
|
157
|
-
*
|
|
158
|
-
* Online-first: awaits the server so a server-side rejection (unique
|
|
159
|
-
* violation, not found, permission denial) surfaces as the typed
|
|
160
|
-
* `KoolbaseDataError` subclass. An update that would violate a unique
|
|
161
|
-
* constraint now throws `KoolbaseConflictError` with the offending field —
|
|
162
|
-
* same shape as `insert` and `upsert`.
|
|
163
|
-
*
|
|
164
|
-
* On genuine network failure the update is queued for sync and a partial
|
|
165
|
-
* optimistic record is returned so the UI can re-render the new fields
|
|
166
|
-
* immediately.
|
|
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;
|
|
181
|
-
update(recordId: string, data: Record<string, unknown>): Promise<KoolbaseRecord>;
|
|
182
|
-
delete(recordId: string): Promise<void>;
|
|
183
|
-
/**
|
|
184
|
-
* Write (or replace) a vector for a record on the named `field`.
|
|
185
|
-
*
|
|
186
|
-
* The field must already be declared on the collection via the dashboard
|
|
187
|
-
* or CLI. `vector.length` must match the field's declared dimension;
|
|
188
|
-
* otherwise throws `KoolbaseVectorDimensionMismatchError`.
|
|
189
|
-
*
|
|
190
|
-
* Online-only — vectors are not cached locally or queued offline because
|
|
191
|
-
* HNSW similarity search has no useful offline semantics.
|
|
192
|
-
*
|
|
193
|
-
* @example
|
|
194
|
-
* await Koolbase.db.setVector(
|
|
195
|
-
* articleId,
|
|
196
|
-
* 'embedding',
|
|
197
|
-
* await myEmbeddingModel.encode(article.content),
|
|
198
|
-
* );
|
|
199
|
-
*/
|
|
200
|
-
setVector(recordId: string, field: string, vector: number[]): Promise<void>;
|
|
201
|
-
/**
|
|
202
|
-
* Read a record's stored vector on the named `field`.
|
|
203
|
-
*
|
|
204
|
-
* Throws `KoolbaseNotFoundError` if either the field is not declared or
|
|
205
|
-
* no vector has been set for this record on this field. Throws
|
|
206
|
-
* `KoolbasePermissionError` if the caller cannot read this record per
|
|
207
|
-
* the collection's read rule.
|
|
208
|
-
*
|
|
209
|
-
* Online-only.
|
|
210
|
-
*
|
|
211
|
-
* @example
|
|
212
|
-
* const v = await Koolbase.db.getVector(articleId, 'embedding');
|
|
213
|
-
* console.log(`${v.vector.length}-dim, updated ${v.updatedAt}`);
|
|
214
|
-
*/
|
|
215
|
-
getVector(recordId: string, field: string): Promise<KoolbaseVector>;
|
|
216
|
-
/**
|
|
217
|
-
* Remove a record's stored vector on the named `field`.
|
|
218
|
-
*
|
|
219
|
-
* Online-only. Throws `KoolbaseNotFoundError` if no vector is set for
|
|
220
|
-
* `(recordId, field)`; throws `KoolbasePermissionError` if the caller
|
|
221
|
-
* cannot write this record per the collection's write rule.
|
|
222
|
-
*
|
|
223
|
-
* Note: this removes the vector from the dimension table but does NOT
|
|
224
|
-
* remove the field declaration itself — the field stays on the
|
|
225
|
-
* collection and is still settable on other records.
|
|
226
|
-
*/
|
|
227
|
-
deleteVector(recordId: string, field: string): Promise<void>;
|
|
228
|
-
/**
|
|
229
|
-
* Queue an embedding job for a record's vector field. The server's
|
|
230
|
-
* embedding worker picks it up within ~1 second.
|
|
231
|
-
*
|
|
232
|
-
* If `text` is omitted, the vector field's configured `source_field`
|
|
233
|
-
* value on the record is used.
|
|
234
|
-
*
|
|
235
|
-
* @example
|
|
236
|
-
* await Koolbase.db.embedText({
|
|
237
|
-
* collection: 'articles',
|
|
238
|
-
* recordId: article.$id,
|
|
239
|
-
* vectorField: 'content_embedding',
|
|
240
|
-
* });
|
|
241
|
-
*/
|
|
242
|
-
embedText(opts: {
|
|
243
|
-
collection: string;
|
|
244
|
-
recordId: string;
|
|
245
|
-
vectorField: string;
|
|
246
|
-
text?: string;
|
|
247
|
-
}): Promise<void>;
|
|
248
|
-
/**
|
|
249
|
-
* Search for records based on their semantic similarity to a query.
|
|
250
|
-
*
|
|
251
|
-
* @example
|
|
252
|
-
* // Server-side embedding — most common:
|
|
253
|
-
* const result = await Koolbase.db.searchSemantic({
|
|
254
|
-
* collection: 'articles',
|
|
255
|
-
* field: 'content_embedding',
|
|
256
|
-
* queryText: 'how do I configure CI/CD?',
|
|
257
|
-
* limit: 10,
|
|
258
|
-
* });
|
|
259
|
-
*
|
|
260
|
-
* // Client-side embedding:
|
|
261
|
-
* const result = await Koolbase.db.searchSemantic({
|
|
262
|
-
* collection: 'articles',
|
|
263
|
-
* field: 'content_embedding',
|
|
264
|
-
* queryVector: precomputed,
|
|
265
|
-
* limit: 10,
|
|
266
|
-
* });
|
|
267
|
-
*
|
|
268
|
-
* // Hybrid search (vector + BM25, RRF-fused):
|
|
269
|
-
* const result = await Koolbase.db.searchSemantic({
|
|
270
|
-
* collection: 'articles',
|
|
271
|
-
* field: 'content_embedding',
|
|
272
|
-
* queryText: 'how do I configure CI/CD?',
|
|
273
|
-
* mode: 'hybrid',
|
|
274
|
-
* minSimilarity: 70,
|
|
275
|
-
* });
|
|
276
|
-
*
|
|
277
|
-
* `mode` selects the retrieval strategy:
|
|
278
|
-
* - `'semantic'` (default) — pure vector search via HNSW
|
|
279
|
-
* - `'lexical'` — pure BM25 over the field's source text
|
|
280
|
-
* - `'hybrid'` — vector + lexical, RRF-fused (k=60)
|
|
281
|
-
*
|
|
282
|
-
* `minSimilarity` (0..100, optional) filters out results below the
|
|
283
|
-
* given similarity percentage server-side. Saves bandwidth on weak
|
|
284
|
-
* matches. Only valid for semantic and hybrid; rejected by the
|
|
285
|
-
* server on lexical mode.
|
|
286
|
-
*/
|
|
287
|
-
searchSemantic(opts: {
|
|
288
|
-
collection: string;
|
|
289
|
-
field: string;
|
|
290
|
-
queryVector?: number[];
|
|
291
|
-
queryText?: string;
|
|
292
|
-
limit?: number;
|
|
293
|
-
where?: Record<string, unknown>;
|
|
294
|
-
mode?: SearchMode;
|
|
295
|
-
minSimilarity?: number;
|
|
296
|
-
}): Promise<SemanticSearchResult>;
|
|
297
|
-
syncPendingWrites(): Promise<void>;
|
|
298
|
-
}
|