@techfinityedge/koolbase-react-native 2.4.0 → 3.1.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 +40 -2
- package/dist/auth.d.ts +8 -0
- package/dist/auth.js +17 -0
- package/dist/database.d.ts +28 -3
- package/dist/database.js +93 -9
- package/dist/functions.d.ts +1 -1
- package/dist/functions.js +1 -1
- package/dist/index.js +3 -3
- package/dist/storage.d.ts +2 -2
- package/dist/storage.js +5 -5
- package/dist/sync-engine.d.ts +2 -1
- package/dist/sync-engine.js +4 -1
- 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:**
|
|
@@ -36,6 +40,13 @@ That's it. Every feature below is now available via `Koolbase.*`.
|
|
|
36
40
|
|
|
37
41
|
---
|
|
38
42
|
|
|
43
|
+
> **Auth is automatic (v3+).** Database, storage, and functions calls
|
|
44
|
+
> authenticate as the currently signed-in user — nothing to pass, no manual
|
|
45
|
+
> wiring. Log in (or restore a session) and every request carries that
|
|
46
|
+
> identity. `owner`/`authenticated` collections require an active session.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
39
50
|
## Authentication
|
|
40
51
|
|
|
41
52
|
Email + password, Apple Sign-In, Google Sign-In, and phone + OTP — out of the box.
|
|
@@ -208,6 +219,8 @@ const deleted = await Koolbase.db.deleteWhere('sessions', {
|
|
|
208
219
|
> A non-empty filter is required. The collection's delete rule applies; for
|
|
209
220
|
> `owner`/`scoped` rules the delete is scoped to your own records. Online-only.
|
|
210
221
|
|
|
222
|
+
---
|
|
223
|
+
|
|
211
224
|
### Offline-first
|
|
212
225
|
|
|
213
226
|
```typescript
|
|
@@ -217,6 +230,31 @@ if (isFromCache) console.log('Served from local cache');
|
|
|
217
230
|
await Koolbase.db.syncPendingWrites();
|
|
218
231
|
```
|
|
219
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
|
+
|
|
220
258
|
---
|
|
221
259
|
|
|
222
260
|
## Storage
|
package/dist/auth.d.ts
CHANGED
|
@@ -132,6 +132,14 @@ export declare class KoolbaseAuth {
|
|
|
132
132
|
unlock(token: string): Promise<void>;
|
|
133
133
|
get currentUser(): KoolbaseUser | null;
|
|
134
134
|
get accessToken(): string | null;
|
|
135
|
+
/**
|
|
136
|
+
* Currently-valid access token for data-plane requests, refreshing
|
|
137
|
+
* (via refresh()) if the cached one is near expiry. Returns null when no
|
|
138
|
+
* session exists or refresh fails — callers then go api-key-only and the
|
|
139
|
+
* server treats it as having no end-user identity. The db/storage/functions
|
|
140
|
+
* clients pull from this per request so identity follows the live session.
|
|
141
|
+
*/
|
|
142
|
+
validAccessToken(): Promise<string | null>;
|
|
135
143
|
setSession(session: KoolbaseSession | null): Promise<void>;
|
|
136
144
|
/**
|
|
137
145
|
* @deprecated v1.9.0: Server endpoint /v1/sdk/auth/oauth not yet
|
package/dist/auth.js
CHANGED
|
@@ -497,6 +497,23 @@ class KoolbaseAuth {
|
|
|
497
497
|
get accessToken() {
|
|
498
498
|
return this.session?.accessToken ?? null;
|
|
499
499
|
}
|
|
500
|
+
/**
|
|
501
|
+
* Currently-valid access token for data-plane requests, refreshing
|
|
502
|
+
* (via refresh()) if the cached one is near expiry. Returns null when no
|
|
503
|
+
* session exists or refresh fails — callers then go api-key-only and the
|
|
504
|
+
* server treats it as having no end-user identity. The db/storage/functions
|
|
505
|
+
* clients pull from this per request so identity follows the live session.
|
|
506
|
+
*/
|
|
507
|
+
async validAccessToken() {
|
|
508
|
+
if (!this.session)
|
|
509
|
+
return null;
|
|
510
|
+
try {
|
|
511
|
+
return await this._ensureValidToken();
|
|
512
|
+
}
|
|
513
|
+
catch {
|
|
514
|
+
return null;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
500
517
|
async setSession(session) {
|
|
501
518
|
if (session) {
|
|
502
519
|
await this.setSessionInternal(session);
|
package/dist/database.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
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;
|
|
5
|
+
private getToken;
|
|
5
6
|
private syncEngine;
|
|
6
|
-
constructor(config: KoolbaseConfig, getUserId: () => string | null);
|
|
7
|
-
private
|
|
7
|
+
constructor(config: KoolbaseConfig, getUserId: () => string | null, getToken: () => Promise<string | null>);
|
|
8
|
+
private buildHeaders;
|
|
8
9
|
private request;
|
|
9
10
|
private runQuery;
|
|
10
11
|
query(collection: string, options?: QueryOptions): Promise<QueryResult>;
|
|
@@ -37,6 +38,30 @@ export declare class KoolbaseDatabase {
|
|
|
37
38
|
* The collection cache is invalidated on success.
|
|
38
39
|
*/
|
|
39
40
|
deleteWhere(collection: string, filters: Record<string, unknown>): Promise<number>;
|
|
41
|
+
/**
|
|
42
|
+
* Run multiple writes as a single atomic transaction.
|
|
43
|
+
*
|
|
44
|
+
* All `operations` commit together or none are applied — the server runs
|
|
45
|
+
* them in one database transaction and rolls back entirely on any failure.
|
|
46
|
+
* Operations apply in order and may span multiple collections.
|
|
47
|
+
*
|
|
48
|
+
* Online-only by design (like `upsert` and `deleteWhere`): atomicity needs
|
|
49
|
+
* the server's authoritative view, so a batch is never queued offline — it
|
|
50
|
+
* throws on network failure. A server-side rejection throws a
|
|
51
|
+
* `KoolbaseDataException` whose message identifies which operation failed;
|
|
52
|
+
* nothing was persisted.
|
|
53
|
+
*
|
|
54
|
+
* Returns one `BatchResult` per operation, in order.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* const results = await Koolbase.db.batch([
|
|
58
|
+
* BatchOp.insert('orders', { total: 50 }),
|
|
59
|
+
* BatchOp.update(inventoryId, { stock: 9 }),
|
|
60
|
+
* BatchOp.upsert('counters', { match: { name: 'orders' }, data: { value: 1 } }),
|
|
61
|
+
* BatchOp.delete(cartItemId),
|
|
62
|
+
* ]);
|
|
63
|
+
*/
|
|
64
|
+
batch(operations: BatchOp[]): Promise<BatchResult[]>;
|
|
40
65
|
get(recordId: string): Promise<KoolbaseRecord>;
|
|
41
66
|
update(recordId: string, data: Record<string, unknown>): Promise<KoolbaseRecord>;
|
|
42
67
|
delete(recordId: string): Promise<void>;
|
package/dist/database.js
CHANGED
|
@@ -8,25 +8,45 @@ 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
|
-
constructor(config, getUserId) {
|
|
29
|
+
constructor(config, getUserId, getToken) {
|
|
13
30
|
this.config = config;
|
|
14
31
|
this.getUserId = getUserId;
|
|
15
|
-
this.
|
|
32
|
+
this.getToken = getToken;
|
|
33
|
+
this.syncEngine = new sync_engine_1.SyncEngine(config, getUserId, getToken);
|
|
16
34
|
this.syncEngine.start();
|
|
17
35
|
}
|
|
18
|
-
|
|
19
|
-
|
|
36
|
+
// getUserId is kept only for local cache keys / offline metadata; request
|
|
37
|
+
// identity now comes solely from the verified access token.
|
|
38
|
+
async buildHeaders() {
|
|
39
|
+
const token = await this.getToken();
|
|
20
40
|
return {
|
|
21
41
|
'Content-Type': 'application/json',
|
|
22
42
|
'x-api-key': this.config.publicKey,
|
|
23
|
-
...(
|
|
43
|
+
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
|
24
44
|
};
|
|
25
45
|
}
|
|
26
46
|
async request(method, path, body) {
|
|
27
47
|
const res = await fetch(`${this.config.baseUrl}${path}`, {
|
|
28
48
|
method,
|
|
29
|
-
headers: this.
|
|
49
|
+
headers: await this.buildHeaders(),
|
|
30
50
|
body: body ? JSON.stringify(body) : undefined,
|
|
31
51
|
});
|
|
32
52
|
const data = await res.json();
|
|
@@ -117,7 +137,7 @@ class KoolbaseDatabase {
|
|
|
117
137
|
async upsert(collection, match, data) {
|
|
118
138
|
const res = await fetch(`${this.config.baseUrl}/v1/sdk/db/upsert`, {
|
|
119
139
|
method: 'POST',
|
|
120
|
-
headers: this.
|
|
140
|
+
headers: await this.buildHeaders(),
|
|
121
141
|
body: JSON.stringify({ collection, match, data }),
|
|
122
142
|
});
|
|
123
143
|
const body = await res.json();
|
|
@@ -146,7 +166,7 @@ class KoolbaseDatabase {
|
|
|
146
166
|
async deleteWhere(collection, filters) {
|
|
147
167
|
const res = await fetch(`${this.config.baseUrl}/v1/sdk/db/delete-where`, {
|
|
148
168
|
method: 'POST',
|
|
149
|
-
headers: this.
|
|
169
|
+
headers: await this.buildHeaders(),
|
|
150
170
|
body: JSON.stringify({ collection, filters }),
|
|
151
171
|
});
|
|
152
172
|
const body = await res.json();
|
|
@@ -157,6 +177,70 @@ class KoolbaseDatabase {
|
|
|
157
177
|
await (0, cache_store_1.invalidateCache)(userId, collection);
|
|
158
178
|
return body.deleted ?? 0;
|
|
159
179
|
}
|
|
180
|
+
// ─── Batch (atomic, online-only) ────────────────────────────────────────────
|
|
181
|
+
/**
|
|
182
|
+
* Run multiple writes as a single atomic transaction.
|
|
183
|
+
*
|
|
184
|
+
* All `operations` commit together or none are applied — the server runs
|
|
185
|
+
* them in one database transaction and rolls back entirely on any failure.
|
|
186
|
+
* Operations apply in order and may span multiple collections.
|
|
187
|
+
*
|
|
188
|
+
* Online-only by design (like `upsert` and `deleteWhere`): atomicity needs
|
|
189
|
+
* the server's authoritative view, so a batch is never queued offline — it
|
|
190
|
+
* throws on network failure. A server-side rejection throws a
|
|
191
|
+
* `KoolbaseDataException` whose message identifies which operation failed;
|
|
192
|
+
* nothing was persisted.
|
|
193
|
+
*
|
|
194
|
+
* Returns one `BatchResult` per operation, in order.
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* const results = await Koolbase.db.batch([
|
|
198
|
+
* BatchOp.insert('orders', { total: 50 }),
|
|
199
|
+
* BatchOp.update(inventoryId, { stock: 9 }),
|
|
200
|
+
* BatchOp.upsert('counters', { match: { name: 'orders' }, data: { value: 1 } }),
|
|
201
|
+
* BatchOp.delete(cartItemId),
|
|
202
|
+
* ]);
|
|
203
|
+
*/
|
|
204
|
+
async batch(operations) {
|
|
205
|
+
if (operations.length === 0) {
|
|
206
|
+
throw new Error('batch requires at least one operation');
|
|
207
|
+
}
|
|
208
|
+
const res = await fetch(`${this.config.baseUrl}/v1/sdk/db/batch`, {
|
|
209
|
+
method: 'POST',
|
|
210
|
+
headers: await this.buildHeaders(),
|
|
211
|
+
body: JSON.stringify({
|
|
212
|
+
operations: operations.map(batchOpToWire),
|
|
213
|
+
}),
|
|
214
|
+
});
|
|
215
|
+
const body = await res.json();
|
|
216
|
+
if (!res.ok) {
|
|
217
|
+
throw (0, database_errors_1.koolbaseDataError)(res.status, body, `Batch failed: ${res.status}`);
|
|
218
|
+
}
|
|
219
|
+
const results = (body.results ?? []).map(r => ({
|
|
220
|
+
type: r.type ?? '',
|
|
221
|
+
record: r.record
|
|
222
|
+
? (0, record_1.recordFromWire)(r.record)
|
|
223
|
+
: undefined,
|
|
224
|
+
created: r.created,
|
|
225
|
+
deleted: r.deleted ?? false,
|
|
226
|
+
}));
|
|
227
|
+
// Keep the cache consistent with what committed. Insert/upsert carry the
|
|
228
|
+
// collection in the input op; update/delete address records by id, so we
|
|
229
|
+
// don't know the collection at this layer — those refresh naturally on
|
|
230
|
+
// the next query for the affected collection.
|
|
231
|
+
const userId = this.getUserId() ?? 'anonymous';
|
|
232
|
+
const touched = new Set();
|
|
233
|
+
for (const op of operations) {
|
|
234
|
+
if (op.type === 'insert' || op.type === 'upsert') {
|
|
235
|
+
touched.add(op.collection);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
for (const col of touched) {
|
|
239
|
+
await (0, cache_store_1.invalidateCache)(userId, col);
|
|
240
|
+
}
|
|
241
|
+
return results;
|
|
242
|
+
}
|
|
243
|
+
// ─── Get single record ──────────────────────────────────────────────────────
|
|
160
244
|
// ─── Get single record ──────────────────────────────────────────────────────
|
|
161
245
|
async get(recordId) {
|
|
162
246
|
const raw = await this.request('GET', `/v1/sdk/db/records/${recordId}`);
|
|
@@ -194,7 +278,7 @@ class KoolbaseDatabase {
|
|
|
194
278
|
recordId,
|
|
195
279
|
});
|
|
196
280
|
// Try network
|
|
197
|
-
const res = await fetch(`${this.config.baseUrl}/v1/sdk/db/records/${recordId}`, { method: 'DELETE', headers: this.
|
|
281
|
+
const res = await fetch(`${this.config.baseUrl}/v1/sdk/db/records/${recordId}`, { method: 'DELETE', headers: await this.buildHeaders(), });
|
|
198
282
|
if (!res.ok && res.status !== 204) {
|
|
199
283
|
// Queued for sync — will retry when online
|
|
200
284
|
}
|
package/dist/functions.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { KoolbaseConfig, FunctionInvokeResult, DeployOptions, DeployResult } fro
|
|
|
2
2
|
export declare class KoolbaseFunctions {
|
|
3
3
|
private config;
|
|
4
4
|
private getUserAccessToken?;
|
|
5
|
-
constructor(config: KoolbaseConfig, getUserAccessToken?: () => string | null);
|
|
5
|
+
constructor(config: KoolbaseConfig, getUserAccessToken?: () => Promise<string | null>);
|
|
6
6
|
deploy(options: DeployOptions): Promise<DeployResult>;
|
|
7
7
|
invoke(name: string, body?: Record<string, unknown>): Promise<FunctionInvokeResult>;
|
|
8
8
|
}
|
package/dist/functions.js
CHANGED
|
@@ -45,7 +45,7 @@ class KoolbaseFunctions {
|
|
|
45
45
|
'Content-Type': 'application/json',
|
|
46
46
|
'x-api-key': this.config.publicKey,
|
|
47
47
|
};
|
|
48
|
-
const userToken = this.getUserAccessToken?.();
|
|
48
|
+
const userToken = await this.getUserAccessToken?.();
|
|
49
49
|
if (userToken) {
|
|
50
50
|
headers['Authorization'] = `Bearer ${userToken}`;
|
|
51
51
|
}
|
package/dist/index.js
CHANGED
|
@@ -67,10 +67,10 @@ exports.Koolbase = {
|
|
|
67
67
|
if (_initialized)
|
|
68
68
|
return;
|
|
69
69
|
_auth = new auth_1.KoolbaseAuth(config);
|
|
70
|
-
_db = new database_1.KoolbaseDatabase(config, () => _auth?.currentUser?.id ?? null);
|
|
71
|
-
_storage = new storage_1.KoolbaseStorage(config, () => _auth?.
|
|
70
|
+
_db = new database_1.KoolbaseDatabase(config, () => _auth?.currentUser?.id ?? null, () => _auth?.validAccessToken() ?? Promise.resolve(null));
|
|
71
|
+
_storage = new storage_1.KoolbaseStorage(config, () => _auth?.validAccessToken() ?? Promise.resolve(null));
|
|
72
72
|
_realtime = new realtime_1.KoolbaseRealtime(config);
|
|
73
|
-
_functions = new functions_1.KoolbaseFunctions(config, () => _auth?.
|
|
73
|
+
_functions = new functions_1.KoolbaseFunctions(config, () => _auth?.validAccessToken() ?? Promise.resolve(null));
|
|
74
74
|
_flags = new flags_1.KoolbaseFlags(config, 'rn-device');
|
|
75
75
|
_codePush = new code_push_1.KoolbaseCodePush(config, config.codePushChannel ?? 'stable');
|
|
76
76
|
// Initialize code push — loads cached bundle then checks in background
|
package/dist/storage.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ import { KoolbaseConfig, UploadOptions } from './types';
|
|
|
2
2
|
export declare class KoolbaseStorage {
|
|
3
3
|
private config;
|
|
4
4
|
private getToken;
|
|
5
|
-
constructor(config: KoolbaseConfig, getToken: () => string | null);
|
|
6
|
-
private
|
|
5
|
+
constructor(config: KoolbaseConfig, getToken: () => Promise<string | null>);
|
|
6
|
+
private buildHeaders;
|
|
7
7
|
upload(options: UploadOptions): Promise<{
|
|
8
8
|
url: string;
|
|
9
9
|
}>;
|
package/dist/storage.js
CHANGED
|
@@ -6,8 +6,8 @@ class KoolbaseStorage {
|
|
|
6
6
|
this.config = config;
|
|
7
7
|
this.getToken = getToken;
|
|
8
8
|
}
|
|
9
|
-
|
|
10
|
-
const token = this.getToken();
|
|
9
|
+
async buildHeaders() {
|
|
10
|
+
const token = await this.getToken();
|
|
11
11
|
return {
|
|
12
12
|
'x-api-key': this.config.publicKey,
|
|
13
13
|
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
|
@@ -17,7 +17,7 @@ class KoolbaseStorage {
|
|
|
17
17
|
// Get presigned upload URL
|
|
18
18
|
const res = await fetch(`${this.config.baseUrl}/v1/sdk/storage/${options.bucket}/upload`, {
|
|
19
19
|
method: 'POST',
|
|
20
|
-
headers: { ...this.
|
|
20
|
+
headers: { ...(await this.buildHeaders()), 'Content-Type': 'application/json' },
|
|
21
21
|
body: JSON.stringify({
|
|
22
22
|
path: options.path,
|
|
23
23
|
content_type: options.file.type,
|
|
@@ -39,7 +39,7 @@ class KoolbaseStorage {
|
|
|
39
39
|
return { url: public_url };
|
|
40
40
|
}
|
|
41
41
|
async getDownloadUrl(bucket, path) {
|
|
42
|
-
const res = await fetch(`${this.config.baseUrl}/v1/sdk/storage/${bucket}/download?path=${encodeURIComponent(path)}`, { headers: this.
|
|
42
|
+
const res = await fetch(`${this.config.baseUrl}/v1/sdk/storage/${bucket}/download?path=${encodeURIComponent(path)}`, { headers: await this.buildHeaders() });
|
|
43
43
|
if (!res.ok) {
|
|
44
44
|
const data = await res.json();
|
|
45
45
|
throw new Error(data.error ?? 'Failed to get download URL');
|
|
@@ -50,7 +50,7 @@ class KoolbaseStorage {
|
|
|
50
50
|
async delete(bucket, path) {
|
|
51
51
|
const res = await fetch(`${this.config.baseUrl}/v1/sdk/storage/${bucket}/delete`, {
|
|
52
52
|
method: 'DELETE',
|
|
53
|
-
headers: { ...this.
|
|
53
|
+
headers: { ...(await this.buildHeaders()), 'Content-Type': 'application/json' },
|
|
54
54
|
body: JSON.stringify({ path }),
|
|
55
55
|
});
|
|
56
56
|
if (!res.ok && res.status !== 204) {
|
package/dist/sync-engine.d.ts
CHANGED
|
@@ -3,10 +3,11 @@ type SyncCallback = () => void;
|
|
|
3
3
|
export declare class SyncEngine {
|
|
4
4
|
private config;
|
|
5
5
|
private getUserId;
|
|
6
|
+
private getToken;
|
|
6
7
|
private onSyncComplete?;
|
|
7
8
|
private unsubscribe?;
|
|
8
9
|
private isSyncing;
|
|
9
|
-
constructor(config: KoolbaseConfig, getUserId: () => string | null, onSyncComplete?: SyncCallback);
|
|
10
|
+
constructor(config: KoolbaseConfig, getUserId: () => string | null, getToken: () => Promise<string | null>, onSyncComplete?: SyncCallback);
|
|
10
11
|
start(): void;
|
|
11
12
|
stop(): void;
|
|
12
13
|
flush(): Promise<void>;
|
package/dist/sync-engine.js
CHANGED
|
@@ -7,10 +7,11 @@ exports.SyncEngine = void 0;
|
|
|
7
7
|
const netinfo_1 = __importDefault(require("@react-native-community/netinfo"));
|
|
8
8
|
const cache_store_1 = require("./cache-store");
|
|
9
9
|
class SyncEngine {
|
|
10
|
-
constructor(config, getUserId, onSyncComplete) {
|
|
10
|
+
constructor(config, getUserId, getToken, onSyncComplete) {
|
|
11
11
|
this.isSyncing = false;
|
|
12
12
|
this.config = config;
|
|
13
13
|
this.getUserId = getUserId;
|
|
14
|
+
this.getToken = getToken;
|
|
14
15
|
this.onSyncComplete = onSyncComplete;
|
|
15
16
|
}
|
|
16
17
|
start() {
|
|
@@ -50,9 +51,11 @@ class SyncEngine {
|
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
53
|
async executeWrite(write) {
|
|
54
|
+
const token = await this.getToken();
|
|
53
55
|
const headers = {
|
|
54
56
|
'Content-Type': 'application/json',
|
|
55
57
|
'x-api-key': this.config.publicKey,
|
|
58
|
+
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
|
56
59
|
};
|
|
57
60
|
if (write.type === 'insert') {
|
|
58
61
|
const res = await fetch(`${this.config.baseUrl}/v1/sdk/db/insert`, {
|
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": "3.1.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",
|