@techfinityedge/koolbase-react-native 3.0.0 → 4.0.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 +55 -2
- package/dist/database-errors.d.ts +5 -4
- package/dist/database-errors.js +5 -4
- package/dist/database.d.ts +50 -1
- package/dist/database.js +155 -38
- package/dist/types.d.ts +39 -0
- package/dist/types.js +17 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,9 +16,13 @@ Auth, database, storage, realtime, functions, feature flags, remote config, vers
|
|
|
16
16
|
3. Add the SDK:
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
|
-
npm install @techfinityedge/koolbase-react-native
|
|
19
|
+
npm install @techfinityedge/koolbase-react-native
|
|
20
20
|
# or
|
|
21
|
-
yarn add @techfinityedge/koolbase-react-native
|
|
21
|
+
yarn add @techfinityedge/koolbase-react-native
|
|
22
|
+
# or
|
|
23
|
+
pnpm add @techfinityedge/koolbase-react-native
|
|
24
|
+
# or
|
|
25
|
+
bun add @techfinityedge/koolbase-react-native
|
|
22
26
|
```
|
|
23
27
|
|
|
24
28
|
**4. Initialize at app startup:**
|
|
@@ -215,6 +219,8 @@ const deleted = await Koolbase.db.deleteWhere('sessions', {
|
|
|
215
219
|
> A non-empty filter is required. The collection's delete rule applies; for
|
|
216
220
|
> `owner`/`scoped` rules the delete is scoped to your own records. Online-only.
|
|
217
221
|
|
|
222
|
+
---
|
|
223
|
+
|
|
218
224
|
### Offline-first
|
|
219
225
|
|
|
220
226
|
```typescript
|
|
@@ -224,6 +230,53 @@ if (isFromCache) console.log('Served from local cache');
|
|
|
224
230
|
await Koolbase.db.syncPendingWrites();
|
|
225
231
|
```
|
|
226
232
|
|
|
233
|
+
### Atomic batch writes
|
|
234
|
+
|
|
235
|
+
Run multiple writes in a single server-side transaction. All operations commit together or none are applied — any failure rolls back the entire batch.
|
|
236
|
+
|
|
237
|
+
```ts
|
|
238
|
+
import { Koolbase, BatchOp } from '@techfinityedge/koolbase-react-native';
|
|
239
|
+
|
|
240
|
+
const results = await Koolbase.db.batch([
|
|
241
|
+
BatchOp.insert('orders', { total: 50, customer_id: customerId }),
|
|
242
|
+
BatchOp.update(inventoryId, { stock: 9 }),
|
|
243
|
+
BatchOp.upsert('counters', {
|
|
244
|
+
match: { name: 'orders' },
|
|
245
|
+
data: { value: 1 },
|
|
246
|
+
}),
|
|
247
|
+
BatchOp.delete(cartItemId),
|
|
248
|
+
]);
|
|
249
|
+
|
|
250
|
+
// results[i] corresponds to operations[i]:
|
|
251
|
+
// - insert / update: { type, record }
|
|
252
|
+
// - upsert: { type, record, created } // created = true if inserted
|
|
253
|
+
// - delete: { type, deleted: true }
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
**Online-only by design.** Atomicity needs the server's authoritative view, so `batch()` is never queued offline — it throws on network failure (like `upsert` and `deleteWhere`). A server-side rejection throws a `KoolbaseDataException` with the failing operation's details; nothing was persisted.
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
### Handling write conflicts
|
|
261
|
+
|
|
262
|
+
`insert`, `update`, and `upsert` are online-first: when the server is reachable they throw a typed error on rejection. Catch `KoolbaseConflictError` to handle unique-constraint violations (e.g. a duplicate email):
|
|
263
|
+
|
|
264
|
+
```ts
|
|
265
|
+
import { KoolbaseConflictError } from '@techfinityedge/koolbase-react-native';
|
|
266
|
+
|
|
267
|
+
try {
|
|
268
|
+
await Koolbase.db.insert('users', { email, name });
|
|
269
|
+
} catch (e) {
|
|
270
|
+
if (e instanceof KoolbaseConflictError) {
|
|
271
|
+
showError(`That ${e.field ?? 'value'} is already in use.`);
|
|
272
|
+
} else {
|
|
273
|
+
throw e;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
When the device is offline, these writes are queued and synced automatically when connectivity returns.
|
|
279
|
+
|
|
227
280
|
---
|
|
228
281
|
|
|
229
282
|
## Storage
|
|
@@ -20,10 +20,11 @@ export declare class KoolbaseDataError extends Error {
|
|
|
20
20
|
* (`details.field`) — useful when a collection has more than one unique
|
|
21
21
|
* constraint and you need to know which value clashed.
|
|
22
22
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
23
|
+
* Surfaced by `insert`, `update`, and `upsert` whenever the server is
|
|
24
|
+
* reachable and rejects the write with a 409. These writes are online-first:
|
|
25
|
+
* a server-side conflict throws immediately. Only a genuine network failure
|
|
26
|
+
* falls back to the offline queue, where a conflict that surfaces at sync
|
|
27
|
+
* time is handled by the sync engine rather than thrown here.
|
|
27
28
|
*
|
|
28
29
|
* @example
|
|
29
30
|
* try {
|
package/dist/database-errors.js
CHANGED
|
@@ -29,10 +29,11 @@ exports.KoolbaseDataError = KoolbaseDataError;
|
|
|
29
29
|
* (`details.field`) — useful when a collection has more than one unique
|
|
30
30
|
* constraint and you need to know which value clashed.
|
|
31
31
|
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
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.
|
|
36
37
|
*
|
|
37
38
|
* @example
|
|
38
39
|
* try {
|
package/dist/database.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { KoolbaseConfig, KoolbaseRecord, QueryOptions, QueryResult, UpsertResult } from './types';
|
|
1
|
+
import { KoolbaseConfig, KoolbaseRecord, QueryOptions, QueryResult, UpsertResult, BatchOp, BatchResult } from './types';
|
|
2
2
|
export declare class KoolbaseDatabase {
|
|
3
3
|
private config;
|
|
4
4
|
private getUserId;
|
|
@@ -9,6 +9,18 @@ export declare class KoolbaseDatabase {
|
|
|
9
9
|
private request;
|
|
10
10
|
private runQuery;
|
|
11
11
|
query(collection: string, options?: QueryOptions): Promise<QueryResult>;
|
|
12
|
+
/**
|
|
13
|
+
* Insert a new record into a collection.
|
|
14
|
+
*
|
|
15
|
+
* Online-first: awaits the server so a server-side rejection (unique
|
|
16
|
+
* violation, validation error, permission denial) surfaces as the typed
|
|
17
|
+
* `KoolbaseDataError` subclass — `insert` now throws `KoolbaseConflictError`
|
|
18
|
+
* with the offending field on a 409, matching `upsert` and `update`.
|
|
19
|
+
*
|
|
20
|
+
* On genuine network failure (server unreachable, timeout) the write is
|
|
21
|
+
* accepted optimistically: saved to the local cache and queued for sync
|
|
22
|
+
* when connectivity returns.
|
|
23
|
+
*/
|
|
12
24
|
insert(collection: string, data: Record<string, unknown>): Promise<KoolbaseRecord>;
|
|
13
25
|
/**
|
|
14
26
|
* Insert a record, or update the existing one matching `match`.
|
|
@@ -38,7 +50,44 @@ export declare class KoolbaseDatabase {
|
|
|
38
50
|
* The collection cache is invalidated on success.
|
|
39
51
|
*/
|
|
40
52
|
deleteWhere(collection: string, filters: Record<string, unknown>): Promise<number>;
|
|
53
|
+
/**
|
|
54
|
+
* Run multiple writes as a single atomic transaction.
|
|
55
|
+
*
|
|
56
|
+
* All `operations` commit together or none are applied — the server runs
|
|
57
|
+
* them in one database transaction and rolls back entirely on any failure.
|
|
58
|
+
* Operations apply in order and may span multiple collections.
|
|
59
|
+
*
|
|
60
|
+
* Online-only by design (like `upsert` and `deleteWhere`): atomicity needs
|
|
61
|
+
* the server's authoritative view, so a batch is never queued offline — it
|
|
62
|
+
* throws on network failure. A server-side rejection throws a
|
|
63
|
+
* `KoolbaseDataException` whose message identifies which operation failed;
|
|
64
|
+
* nothing was persisted.
|
|
65
|
+
*
|
|
66
|
+
* Returns one `BatchResult` per operation, in order.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* const results = await Koolbase.db.batch([
|
|
70
|
+
* BatchOp.insert('orders', { total: 50 }),
|
|
71
|
+
* BatchOp.update(inventoryId, { stock: 9 }),
|
|
72
|
+
* BatchOp.upsert('counters', { match: { name: 'orders' }, data: { value: 1 } }),
|
|
73
|
+
* BatchOp.delete(cartItemId),
|
|
74
|
+
* ]);
|
|
75
|
+
*/
|
|
76
|
+
batch(operations: BatchOp[]): Promise<BatchResult[]>;
|
|
41
77
|
get(recordId: string): Promise<KoolbaseRecord>;
|
|
78
|
+
/**
|
|
79
|
+
* Update a record's fields by id.
|
|
80
|
+
*
|
|
81
|
+
* Online-first: awaits the server so a server-side rejection (unique
|
|
82
|
+
* violation, not found, permission denial) surfaces as the typed
|
|
83
|
+
* `KoolbaseDataError` subclass. An update that would violate a unique
|
|
84
|
+
* constraint now throws `KoolbaseConflictError` with the offending field —
|
|
85
|
+
* same shape as `insert` and `upsert`.
|
|
86
|
+
*
|
|
87
|
+
* On genuine network failure the update is queued for sync and a partial
|
|
88
|
+
* optimistic record is returned so the UI can re-render the new fields
|
|
89
|
+
* immediately.
|
|
90
|
+
*/
|
|
42
91
|
update(recordId: string, data: Record<string, unknown>): Promise<KoolbaseRecord>;
|
|
43
92
|
delete(recordId: string): Promise<void>;
|
|
44
93
|
syncPendingWrites(): Promise<void>;
|
package/dist/database.js
CHANGED
|
@@ -8,6 +8,23 @@ const database_errors_1 = require("./database-errors");
|
|
|
8
8
|
function generateId() {
|
|
9
9
|
return 'local_' + Math.random().toString(36).slice(2) + Date.now().toString(36);
|
|
10
10
|
}
|
|
11
|
+
function batchOpToWire(op) {
|
|
12
|
+
switch (op.type) {
|
|
13
|
+
case 'insert':
|
|
14
|
+
return { type: 'insert', collection: op.collection, data: op.data };
|
|
15
|
+
case 'update':
|
|
16
|
+
return { type: 'update', record_id: op.recordId, data: op.data };
|
|
17
|
+
case 'delete':
|
|
18
|
+
return { type: 'delete', record_id: op.recordId };
|
|
19
|
+
case 'upsert':
|
|
20
|
+
return {
|
|
21
|
+
type: 'upsert',
|
|
22
|
+
collection: op.collection,
|
|
23
|
+
match: op.match,
|
|
24
|
+
data: op.data,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
11
28
|
class KoolbaseDatabase {
|
|
12
29
|
constructor(config, getUserId, getToken) {
|
|
13
30
|
this.config = config;
|
|
@@ -67,39 +84,56 @@ class KoolbaseDatabase {
|
|
|
67
84
|
await (0, cache_store_1.setCached)(userId, collection, queryHash, result);
|
|
68
85
|
return { ...result, isFromCache: false };
|
|
69
86
|
}
|
|
70
|
-
// ─── Insert (
|
|
87
|
+
// ─── Insert (online-first with offline fallback) ───────────────────────────
|
|
88
|
+
/**
|
|
89
|
+
* Insert a new record into a collection.
|
|
90
|
+
*
|
|
91
|
+
* Online-first: awaits the server so a server-side rejection (unique
|
|
92
|
+
* violation, validation error, permission denial) surfaces as the typed
|
|
93
|
+
* `KoolbaseDataError` subclass — `insert` now throws `KoolbaseConflictError`
|
|
94
|
+
* with the offending field on a 409, matching `upsert` and `update`.
|
|
95
|
+
*
|
|
96
|
+
* On genuine network failure (server unreachable, timeout) the write is
|
|
97
|
+
* accepted optimistically: saved to the local cache and queued for sync
|
|
98
|
+
* when connectivity returns.
|
|
99
|
+
*/
|
|
71
100
|
async insert(collection, data) {
|
|
72
101
|
const userId = this.getUserId() ?? 'anonymous';
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
data
|
|
78
|
-
|
|
79
|
-
updatedAt: new Date().toISOString(),
|
|
80
|
-
};
|
|
81
|
-
// Write to local cache immediately
|
|
82
|
-
await (0, cache_store_1.optimisticallyInsert)(userId, collection, optimisticRecord);
|
|
83
|
-
// Add to write queue
|
|
84
|
-
await (0, cache_store_1.addToWriteQueue)(userId, {
|
|
85
|
-
id: generateId(),
|
|
86
|
-
type: 'insert',
|
|
87
|
-
collection,
|
|
88
|
-
data,
|
|
89
|
-
});
|
|
90
|
-
// Try network in background
|
|
91
|
-
this.request('POST', '/v1/sdk/db/insert', {
|
|
92
|
-
collection,
|
|
93
|
-
data,
|
|
94
|
-
})
|
|
95
|
-
.then(async (serverRecord) => {
|
|
96
|
-
// Invalidate cache so next query gets real data
|
|
102
|
+
try {
|
|
103
|
+
// Online path: await the server and return the authoritative record
|
|
104
|
+
// (with the server-assigned id). Refresh the collection cache so the
|
|
105
|
+
// next query sees real data instead of a stale optimistic copy.
|
|
106
|
+
const raw = await this.request('POST', '/v1/sdk/db/insert', { collection, data });
|
|
107
|
+
const record = (0, record_1.recordFromWire)(raw);
|
|
97
108
|
await (0, cache_store_1.invalidateCache)(userId, collection);
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
109
|
+
return record;
|
|
110
|
+
}
|
|
111
|
+
catch (e) {
|
|
112
|
+
// Server-reachable rejection: the server saw the request and refused.
|
|
113
|
+
// Surface to the caller without writing optimistic state or queuing —
|
|
114
|
+
// the server has already decided it will not accept this write, and
|
|
115
|
+
// queuing it would just spin SyncEngine until max retries.
|
|
116
|
+
if (e instanceof database_errors_1.KoolbaseDataError)
|
|
117
|
+
throw e;
|
|
118
|
+
// Genuine network failure → offline path: save to local cache and
|
|
119
|
+
// queue for SyncEngine to retry when online. Return the optimistic
|
|
120
|
+
// record so the UI has something to render in the meantime.
|
|
121
|
+
const optimisticRecord = {
|
|
122
|
+
id: generateId(),
|
|
123
|
+
createdBy: userId,
|
|
124
|
+
data,
|
|
125
|
+
createdAt: new Date().toISOString(),
|
|
126
|
+
updatedAt: new Date().toISOString(),
|
|
127
|
+
};
|
|
128
|
+
await (0, cache_store_1.optimisticallyInsert)(userId, collection, optimisticRecord);
|
|
129
|
+
await (0, cache_store_1.addToWriteQueue)(userId, {
|
|
130
|
+
id: generateId(),
|
|
131
|
+
type: 'insert',
|
|
132
|
+
collection,
|
|
133
|
+
data,
|
|
134
|
+
});
|
|
135
|
+
return optimisticRecord;
|
|
136
|
+
}
|
|
103
137
|
}
|
|
104
138
|
// ─── Upsert (online-only) ─────────────────────────────────────────────────
|
|
105
139
|
/**
|
|
@@ -160,25 +194,108 @@ class KoolbaseDatabase {
|
|
|
160
194
|
await (0, cache_store_1.invalidateCache)(userId, collection);
|
|
161
195
|
return body.deleted ?? 0;
|
|
162
196
|
}
|
|
197
|
+
// ─── Batch (atomic, online-only) ────────────────────────────────────────────
|
|
198
|
+
/**
|
|
199
|
+
* Run multiple writes as a single atomic transaction.
|
|
200
|
+
*
|
|
201
|
+
* All `operations` commit together or none are applied — the server runs
|
|
202
|
+
* them in one database transaction and rolls back entirely on any failure.
|
|
203
|
+
* Operations apply in order and may span multiple collections.
|
|
204
|
+
*
|
|
205
|
+
* Online-only by design (like `upsert` and `deleteWhere`): atomicity needs
|
|
206
|
+
* the server's authoritative view, so a batch is never queued offline — it
|
|
207
|
+
* throws on network failure. A server-side rejection throws a
|
|
208
|
+
* `KoolbaseDataException` whose message identifies which operation failed;
|
|
209
|
+
* nothing was persisted.
|
|
210
|
+
*
|
|
211
|
+
* Returns one `BatchResult` per operation, in order.
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* const results = await Koolbase.db.batch([
|
|
215
|
+
* BatchOp.insert('orders', { total: 50 }),
|
|
216
|
+
* BatchOp.update(inventoryId, { stock: 9 }),
|
|
217
|
+
* BatchOp.upsert('counters', { match: { name: 'orders' }, data: { value: 1 } }),
|
|
218
|
+
* BatchOp.delete(cartItemId),
|
|
219
|
+
* ]);
|
|
220
|
+
*/
|
|
221
|
+
async batch(operations) {
|
|
222
|
+
if (operations.length === 0) {
|
|
223
|
+
throw new Error('batch requires at least one operation');
|
|
224
|
+
}
|
|
225
|
+
const res = await fetch(`${this.config.baseUrl}/v1/sdk/db/batch`, {
|
|
226
|
+
method: 'POST',
|
|
227
|
+
headers: await this.buildHeaders(),
|
|
228
|
+
body: JSON.stringify({
|
|
229
|
+
operations: operations.map(batchOpToWire),
|
|
230
|
+
}),
|
|
231
|
+
});
|
|
232
|
+
const body = await res.json();
|
|
233
|
+
if (!res.ok) {
|
|
234
|
+
throw (0, database_errors_1.koolbaseDataError)(res.status, body, `Batch failed: ${res.status}`);
|
|
235
|
+
}
|
|
236
|
+
const results = (body.results ?? []).map(r => ({
|
|
237
|
+
type: r.type ?? '',
|
|
238
|
+
record: r.record
|
|
239
|
+
? (0, record_1.recordFromWire)(r.record)
|
|
240
|
+
: undefined,
|
|
241
|
+
created: r.created,
|
|
242
|
+
deleted: r.deleted ?? false,
|
|
243
|
+
}));
|
|
244
|
+
// Keep the cache consistent with what committed. Insert/upsert carry the
|
|
245
|
+
// collection in the input op; update/delete address records by id, so we
|
|
246
|
+
// don't know the collection at this layer — those refresh naturally on
|
|
247
|
+
// the next query for the affected collection.
|
|
248
|
+
const userId = this.getUserId() ?? 'anonymous';
|
|
249
|
+
const touched = new Set();
|
|
250
|
+
for (const op of operations) {
|
|
251
|
+
if (op.type === 'insert' || op.type === 'upsert') {
|
|
252
|
+
touched.add(op.collection);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
for (const col of touched) {
|
|
256
|
+
await (0, cache_store_1.invalidateCache)(userId, col);
|
|
257
|
+
}
|
|
258
|
+
return results;
|
|
259
|
+
}
|
|
260
|
+
// ─── Get single record ──────────────────────────────────────────────────────
|
|
163
261
|
// ─── Get single record ──────────────────────────────────────────────────────
|
|
164
262
|
async get(recordId) {
|
|
165
263
|
const raw = await this.request('GET', `/v1/sdk/db/records/${recordId}`);
|
|
166
264
|
return (0, record_1.recordFromWire)(raw);
|
|
167
265
|
}
|
|
168
|
-
// ─── Update
|
|
266
|
+
// ─── Update (online-first with offline fallback) ───────────────────────────
|
|
267
|
+
/**
|
|
268
|
+
* Update a record's fields by id.
|
|
269
|
+
*
|
|
270
|
+
* Online-first: awaits the server so a server-side rejection (unique
|
|
271
|
+
* violation, not found, permission denial) surfaces as the typed
|
|
272
|
+
* `KoolbaseDataError` subclass. An update that would violate a unique
|
|
273
|
+
* constraint now throws `KoolbaseConflictError` with the offending field —
|
|
274
|
+
* same shape as `insert` and `upsert`.
|
|
275
|
+
*
|
|
276
|
+
* On genuine network failure the update is queued for sync and a partial
|
|
277
|
+
* optimistic record is returned so the UI can re-render the new fields
|
|
278
|
+
* immediately.
|
|
279
|
+
*/
|
|
169
280
|
async update(recordId, data) {
|
|
170
281
|
const userId = this.getUserId() ?? 'anonymous';
|
|
171
|
-
await (0, cache_store_1.addToWriteQueue)(userId, {
|
|
172
|
-
id: generateId(),
|
|
173
|
-
type: 'update',
|
|
174
|
-
recordId,
|
|
175
|
-
data,
|
|
176
|
-
});
|
|
177
282
|
try {
|
|
178
283
|
const raw = await this.request('PATCH', `/v1/sdk/db/records/${recordId}`, { data });
|
|
179
284
|
return (0, record_1.recordFromWire)(raw);
|
|
180
285
|
}
|
|
181
|
-
catch {
|
|
286
|
+
catch (e) {
|
|
287
|
+
// Server-reachable rejection: surface to caller without queuing — the
|
|
288
|
+
// server already refused the write and will refuse it again on retry.
|
|
289
|
+
if (e instanceof database_errors_1.KoolbaseDataError)
|
|
290
|
+
throw e;
|
|
291
|
+
// Genuine network failure → queue for sync and return an optimistic
|
|
292
|
+
// partial record so the UI reflects the update immediately.
|
|
293
|
+
await (0, cache_store_1.addToWriteQueue)(userId, {
|
|
294
|
+
id: generateId(),
|
|
295
|
+
type: 'update',
|
|
296
|
+
recordId,
|
|
297
|
+
data,
|
|
298
|
+
});
|
|
182
299
|
return {
|
|
183
300
|
id: recordId,
|
|
184
301
|
data,
|
package/dist/types.d.ts
CHANGED
|
@@ -243,3 +243,42 @@ export interface SignInWithGoogleParams {
|
|
|
243
243
|
idToken: string;
|
|
244
244
|
nonce?: string;
|
|
245
245
|
}
|
|
246
|
+
export type BatchOp = {
|
|
247
|
+
type: 'insert';
|
|
248
|
+
collection: string;
|
|
249
|
+
data: Record<string, unknown>;
|
|
250
|
+
} | {
|
|
251
|
+
type: 'update';
|
|
252
|
+
recordId: string;
|
|
253
|
+
data: Record<string, unknown>;
|
|
254
|
+
} | {
|
|
255
|
+
type: 'delete';
|
|
256
|
+
recordId: string;
|
|
257
|
+
} | {
|
|
258
|
+
type: 'upsert';
|
|
259
|
+
collection: string;
|
|
260
|
+
match: Record<string, unknown>;
|
|
261
|
+
data: Record<string, unknown>;
|
|
262
|
+
};
|
|
263
|
+
/**
|
|
264
|
+
* Factory helpers for constructing batch operations. Same shape as
|
|
265
|
+
* Flutter's `KoolbaseBatchOp.insert(...)` etc., so the mental model
|
|
266
|
+
* transfers between platforms.
|
|
267
|
+
*/
|
|
268
|
+
export declare const BatchOp: {
|
|
269
|
+
insert: (collection: string, data: Record<string, unknown>) => BatchOp;
|
|
270
|
+
update: (recordId: string, data: Record<string, unknown>) => BatchOp;
|
|
271
|
+
delete: (recordId: string) => BatchOp;
|
|
272
|
+
upsert: (collection: string, opts: {
|
|
273
|
+
match: Record<string, unknown>;
|
|
274
|
+
data: Record<string, unknown>;
|
|
275
|
+
}) => BatchOp;
|
|
276
|
+
};
|
|
277
|
+
export interface BatchResult {
|
|
278
|
+
type: string;
|
|
279
|
+
record?: KoolbaseRecord;
|
|
280
|
+
/** For upsert: true if a new record was inserted, false if one was updated. */
|
|
281
|
+
created?: boolean;
|
|
282
|
+
/** True for a successful delete. */
|
|
283
|
+
deleted?: boolean;
|
|
284
|
+
}
|
package/dist/types.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.FunctionRuntime = exports.RestoreResult = void 0;
|
|
3
|
+
exports.BatchOp = exports.FunctionRuntime = exports.RestoreResult = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Result of KoolbaseAuth.restoreSession(). Apps should branch on this:
|
|
6
6
|
* - NoSession → show login screen
|
|
@@ -22,3 +22,19 @@ var FunctionRuntime;
|
|
|
22
22
|
FunctionRuntime["Deno"] = "deno";
|
|
23
23
|
FunctionRuntime["Dart"] = "dart";
|
|
24
24
|
})(FunctionRuntime || (exports.FunctionRuntime = FunctionRuntime = {}));
|
|
25
|
+
/**
|
|
26
|
+
* Factory helpers for constructing batch operations. Same shape as
|
|
27
|
+
* Flutter's `KoolbaseBatchOp.insert(...)` etc., so the mental model
|
|
28
|
+
* transfers between platforms.
|
|
29
|
+
*/
|
|
30
|
+
exports.BatchOp = {
|
|
31
|
+
insert: (collection, data) => ({ type: 'insert', collection, data }),
|
|
32
|
+
update: (recordId, data) => ({ type: 'update', recordId, data }),
|
|
33
|
+
delete: (recordId) => ({ type: 'delete', recordId }),
|
|
34
|
+
upsert: (collection, opts) => ({
|
|
35
|
+
type: 'upsert',
|
|
36
|
+
collection,
|
|
37
|
+
match: opts.match,
|
|
38
|
+
data: opts.data,
|
|
39
|
+
}),
|
|
40
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@techfinityedge/koolbase-react-native",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "React Native SDK for Koolbase \u2014 auth, database, storage, realtime, feature flags, and functions in one package.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|