@koolbase/react-native 9.1.0 → 10.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.
Files changed (59) hide show
  1. package/CHANGELOG.md +1342 -0
  2. package/README.md +462 -511
  3. package/dist/{auth-storage.d.ts → cjs/auth-storage.d.ts} +1 -1
  4. package/dist/cjs/index.d.ts +19 -0
  5. package/dist/cjs/index.js +125 -0
  6. package/dist/cjs/package.json +3 -0
  7. package/dist/cjs/platform.d.ts +2 -0
  8. package/dist/cjs/platform.js +43 -0
  9. package/dist/esm/auth-storage.d.ts +26 -0
  10. package/dist/esm/auth-storage.js +100 -0
  11. package/dist/esm/index.d.ts +19 -0
  12. package/dist/esm/index.js +106 -0
  13. package/dist/esm/package.json +3 -0
  14. package/dist/esm/platform.d.ts +2 -0
  15. package/dist/esm/platform.js +37 -0
  16. package/package.json +30 -24
  17. package/dist/analytics.d.ts +0 -24
  18. package/dist/analytics.js +0 -114
  19. package/dist/apple-auth.d.ts +0 -22
  20. package/dist/apple-auth.js +0 -74
  21. package/dist/auth-errors.d.ts +0 -117
  22. package/dist/auth-errors.js +0 -250
  23. package/dist/auth.d.ts +0 -199
  24. package/dist/auth.js +0 -794
  25. package/dist/cache-store.d.ts +0 -11
  26. package/dist/cache-store.js +0 -136
  27. package/dist/code-push.d.ts +0 -59
  28. package/dist/code-push.js +0 -255
  29. package/dist/database-errors.d.ts +0 -95
  30. package/dist/database-errors.js +0 -173
  31. package/dist/database.d.ts +0 -208
  32. package/dist/database.js +0 -508
  33. package/dist/device-id.d.ts +0 -1
  34. package/dist/device-id.js +0 -60
  35. package/dist/device-metadata.d.ts +0 -36
  36. package/dist/device-metadata.js +0 -102
  37. package/dist/flags.d.ts +0 -15
  38. package/dist/flags.js +0 -76
  39. package/dist/functions.d.ts +0 -8
  40. package/dist/functions.js +0 -70
  41. package/dist/index.d.ts +0 -45
  42. package/dist/index.js +0 -193
  43. package/dist/logic-engine.d.ts +0 -17
  44. package/dist/logic-engine.js +0 -193
  45. package/dist/messaging.d.ts +0 -13
  46. package/dist/messaging.js +0 -36
  47. package/dist/realtime.d.ts +0 -19
  48. package/dist/realtime.js +0 -148
  49. package/dist/record.d.ts +0 -2
  50. package/dist/record.js +0 -20
  51. package/dist/storage-errors.d.ts +0 -163
  52. package/dist/storage-errors.js +0 -249
  53. package/dist/storage.d.ts +0 -184
  54. package/dist/storage.js +0 -438
  55. package/dist/sync-engine.d.ts +0 -16
  56. package/dist/sync-engine.js +0 -86
  57. package/dist/types.d.ts +0 -470
  58. package/dist/types.js +0 -40
  59. /package/dist/{auth-storage.js → cjs/auth-storage.js} +0 -0
package/dist/storage.js DELETED
@@ -1,438 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.KoolbaseStorage = void 0;
4
- const storage_errors_1 = require("./storage-errors");
5
- // --- Cloudflare image-transform URL helpers -------------------------------
6
- // Module-private — callers use KoolbaseStorage.publicUrl / publicUrlForObject.
7
- function clampInt(v, min, max) {
8
- return Math.max(min, Math.min(max, Math.floor(v)));
9
- }
10
- /**
11
- * Serializes a transform spec to Cloudflare's comma-separated key=value
12
- * options segment (e.g. `width=400,format=webp,quality=80`). Returns the
13
- * empty string when no fields are set — callers can use that to skip the
14
- * `/cdn-cgi/image/` URL prefix entirely.
15
- */
16
- function serializeTransform(t) {
17
- const parts = [];
18
- if (t.width != null)
19
- parts.push(`width=${clampInt(t.width, 1, 2000)}`);
20
- if (t.height != null)
21
- parts.push(`height=${clampInt(t.height, 1, 2000)}`);
22
- if (t.format)
23
- parts.push(`format=${t.format}`);
24
- if (t.quality != null)
25
- parts.push(`quality=${clampInt(t.quality, 1, 100)}`);
26
- if (t.fit)
27
- parts.push(`fit=${t.fit}`);
28
- if (t.dpr != null)
29
- parts.push(`dpr=${clampInt(t.dpr, 1, 3)}`);
30
- if (t.gravity)
31
- parts.push(`gravity=${t.gravity}`);
32
- return parts.join(',');
33
- }
34
- /**
35
- * Koolbase storage client — uploads, downloads, and deletes via presigned
36
- * Cloudflare R2 URLs.
37
- *
38
- * Uploads are **safe-by-default** (v5+): an upload to a path where an object
39
- * already exists is rejected with {@link KoolbaseStorageConflictError} unless
40
- * `overwrite: true` is passed.
41
- */
42
- class KoolbaseStorage {
43
- constructor(config, getToken) {
44
- this.config = config;
45
- this.getToken = getToken;
46
- }
47
- async buildHeaders() {
48
- const token = await this.getToken();
49
- return {
50
- 'x-api-key': this.config.publicKey,
51
- ...(token ? { Authorization: `Bearer ${token}` } : {}),
52
- };
53
- }
54
- /**
55
- * Upload a file to a bucket. Returns the object metadata and a download URL.
56
- *
57
- * By default (`overwrite: false`), uploads to a path where an object
58
- * already exists are **rejected** with a {@link KoolbaseStorageConflictError}.
59
- * Catch it to prompt the user, then retry with `overwrite: true` to replace
60
- * the existing object — or with a different `path`.
61
- *
62
- * Set `overwrite: true` for true upsert semantics — silently replace any
63
- * existing object at this path.
64
- *
65
- * Pass `options.metadata` to attach arbitrary user-defined key/value pairs
66
- * to the object at confirm time. Subject to the limits documented on
67
- * {@link KoolbaseObject.metadata}; violations throw
68
- * `KoolbaseStorageMetadataInvalidError`. On the `overwrite: true` path the
69
- * metadata REPLACES any prior metadata at this path (matches GCS semantics).
70
- * Use {@link updateMetadata} for post-upload merge changes.
71
- *
72
- * **Breaking change in v5.0.0**: the default flipped from silent overwrite
73
- * (legacy behavior) to safe-by-default. If you previously relied on uploads
74
- * overwriting silently, pass `overwrite: true` explicitly.
75
- */
76
- async upload(options) {
77
- const overwrite = options.overwrite ?? false;
78
- const contentType = options.file.type;
79
- // ─── Step 1: Get presigned upload URL ───
80
- const urlRes = await fetch(`${this.config.baseUrl}/v1/sdk/storage/upload-url`, {
81
- method: 'POST',
82
- headers: {
83
- ...(await this.buildHeaders()),
84
- 'Content-Type': 'application/json',
85
- },
86
- body: JSON.stringify({
87
- bucket: options.bucket,
88
- path: options.path,
89
- content_type: contentType,
90
- overwrite,
91
- }),
92
- });
93
- if (!urlRes.ok) {
94
- throw await (0, storage_errors_1.koolbaseStorageErrorFromResponse)(urlRes, 'Failed to get upload URL');
95
- }
96
- const { upload_url } = (await urlRes.json());
97
- // ─── Step 2: Upload directly to R2 ───
98
- // RN's fetch resolves local file URIs and Blob bodies on a raw PUT.
99
- // R2 presigned URLs expect raw binary, NOT multipart/form-data.
100
- const fileResp = await fetch(options.file.uri);
101
- const fileBlob = await fileResp.blob();
102
- const fileSize = fileBlob.size;
103
- const uploadRes = await fetch(upload_url, {
104
- method: 'PUT',
105
- headers: { 'Content-Type': contentType },
106
- body: fileBlob,
107
- });
108
- if (!uploadRes.ok) {
109
- // R2 PUT errors don't follow the Koolbase error shape — surface as a
110
- // generic storage error rather than trying to decode a Koolbase body.
111
- throw new storage_errors_1.KoolbaseStorageError(`Upload to storage failed: ${uploadRes.status}`);
112
- }
113
- const etag = uploadRes.headers.get('etag') ?? '';
114
- // ─── Step 3: Confirm upload ───
115
- // Build the body conditionally so the `metadata` field is only sent
116
- // when the caller passed it — keeps the wire shape clean for callers
117
- // that don't care, and lets the server's omitempty path treat absent
118
- // as "no metadata."
119
- const confirmBody = {
120
- bucket: options.bucket,
121
- path: options.path,
122
- size: fileSize,
123
- content_type: contentType,
124
- etag,
125
- overwrite,
126
- };
127
- if (options.metadata !== undefined) {
128
- confirmBody.metadata = options.metadata;
129
- }
130
- const confirmRes = await fetch(`${this.config.baseUrl}/v1/sdk/storage/confirm`, {
131
- method: 'POST',
132
- headers: {
133
- ...(await this.buildHeaders()),
134
- 'Content-Type': 'application/json',
135
- },
136
- body: JSON.stringify(confirmBody),
137
- });
138
- if (!confirmRes.ok) {
139
- throw await (0, storage_errors_1.koolbaseStorageErrorFromResponse)(confirmRes, 'Failed to confirm upload');
140
- }
141
- const raw = await confirmRes.json();
142
- const object = mapObjectFromServer(raw);
143
- // ─── Step 4: Get download URL ───
144
- const downloadUrl = await this.getDownloadUrl(options.bucket, options.path);
145
- return { object, downloadUrl };
146
- }
147
- /**
148
- * Apply a partial metadata update to an existing object. Returns the
149
- * post-update {@link KoolbaseObject} with the merged metadata.
150
- *
151
- * **Merge semantics** (mirrors the server's JSONB merge):
152
- *
153
- * - Keys with a non-null string value are SET — added if missing,
154
- * replacing any existing value at the key otherwise.
155
- * - Keys with `null` are DELETED from the stored metadata.
156
- * - Keys ABSENT from `metadata` are untouched — pre-existing entries
157
- * for those keys remain unchanged.
158
- *
159
- * Validation runs server-side against the same rules as upload-time
160
- * metadata; violations throw `KoolbaseStorageMetadataInvalidError`,
161
- * whose `detail` field names the failing key and rule. The check is
162
- * performed against the projected post-merge state, so adding a key
163
- * that would push the object past the 50-key or 8KB ceiling is
164
- * rejected before the row is mutated.
165
- *
166
- * @example
167
- * // Add a tag, update an existing key, and drop another in one call:
168
- * const updated = await Koolbase.storage.updateMetadata(
169
- * 'photos',
170
- * 'sunset.jpg',
171
- * {
172
- * category: 'landscape', // SET or UPDATE
173
- * tag: 'sunset', // SET or UPDATE
174
- * owner: null, // DELETE
175
- * }
176
- * );
177
- * console.log(updated.metadata);
178
- * // -> { category: 'landscape', tag: 'sunset' }
179
- */
180
- async updateMetadata(bucket, path, metadata) {
181
- const res = await fetch(`${this.config.baseUrl}/v1/sdk/storage/objects/metadata`, {
182
- method: 'PATCH',
183
- headers: {
184
- ...(await this.buildHeaders()),
185
- 'Content-Type': 'application/json',
186
- },
187
- body: JSON.stringify({ bucket, path, metadata }),
188
- });
189
- if (!res.ok) {
190
- throw await (0, storage_errors_1.koolbaseStorageErrorFromResponse)(res, 'Failed to update metadata');
191
- }
192
- const raw = await res.json();
193
- return mapObjectFromServer(raw);
194
- }
195
- /**
196
- * Get a signed download URL for a file.
197
- */
198
- async getDownloadUrl(bucket, path, versionId) {
199
- let url = `${this.config.baseUrl}/v1/sdk/storage/download-url` +
200
- `?bucket=${encodeURIComponent(bucket)}&path=${encodeURIComponent(path)}`;
201
- if (versionId) {
202
- url += `&version_id=${encodeURIComponent(versionId)}`;
203
- }
204
- const res = await fetch(url, { headers: await this.buildHeaders() });
205
- if (!res.ok) {
206
- throw await (0, storage_errors_1.koolbaseStorageErrorFromResponse)(res, 'Failed to get download URL');
207
- }
208
- const data = (await res.json());
209
- return data.url;
210
- }
211
- /**
212
- * Build the stable public CDN URL for a file in a public bucket.
213
- *
214
- * Returns the URL unconditionally — no check on whether the file
215
- * exists or whether the bucket is actually public. Use when you
216
- * know the file is in a public bucket and want the URL without a
217
- * network round-trip (build-time URL generation, server-side
218
- * rendering, batch image processing, etc.).
219
- *
220
- * For safer construction from an Object you already have, use
221
- * {@link KoolbaseStorage.publicUrlForObject} — it checks the stored
222
- * `r2Bucket` value and returns `null` when the object isn't in the
223
- * public R2 bucket.
224
- */
225
- static publicUrl(args) {
226
- // Encode each path segment individually so slashes are preserved
227
- // while spaces, parens, hashes, and query characters are escaped.
228
- const encoded = args.path.split('/').map(encodeURIComponent).join('/');
229
- const opts = args.transform ? serializeTransform(args.transform) : '';
230
- if (!opts) {
231
- return `https://cdn.koolbase.com/${args.projectId}/${args.bucket}/${encoded}`;
232
- }
233
- return `https://cdn.koolbase.com/cdn-cgi/image/${opts}/${args.projectId}/${args.bucket}/${encoded}`;
234
- }
235
- /**
236
- * Returns the stable CDN URL for an object when its bytes physically
237
- * live in the public R2 bucket, `null` otherwise.
238
- *
239
- * Returns `null` for:
240
- * - Files in private buckets (no public URL ever)
241
- * - Legacy files in public buckets whose bytes still live in the
242
- * private R2 bucket from before Gap #2 (no permanent URL until
243
- * they're re-uploaded)
244
- *
245
- * The bucket name must be supplied because {@link KoolbaseObject}
246
- * carries only the bucket ID, not its name. Typically the caller
247
- * already knows which bucket they queried.
248
- */
249
- static publicUrlForObject(obj, bucket, options) {
250
- if (obj.r2Bucket !== 'koolbase-storage-public')
251
- return null;
252
- return KoolbaseStorage.publicUrl({
253
- projectId: obj.projectId,
254
- bucket,
255
- path: obj.path,
256
- transform: options?.transform,
257
- });
258
- }
259
- /**
260
- * Builds a named-preset CDN URL. The preset is resolved at the Cloudflare
261
- * edge by the koolbase-cdn-worker, which looks up
262
- * `preset:{project_id}:{preset_name}` in Workers KV and applies the stored
263
- * transformation options. Presets are managed in the dashboard under
264
- * Storage → Presets.
265
- *
266
- * Unknown preset names yield a 404 at the edge — the URL itself always
267
- * constructs successfully without a network round-trip.
268
- *
269
- * For safer construction from an Object you already have, use
270
- * {@link KoolbaseStorage.publicUrlForObjectWithPreset} — it checks the
271
- * stored `r2Bucket` value and returns `null` when the object isn't in the
272
- * public R2 bucket.
273
- */
274
- static publicUrlWithPreset(args) {
275
- const encoded = args.path.split('/').map(encodeURIComponent).join('/');
276
- return `https://cdn.koolbase.com/p/${args.projectId}/${args.presetName}/${args.bucket}/${encoded}`;
277
- }
278
- /**
279
- * Returns the named-preset CDN URL for the given object, or `null` if the
280
- * object isn't in the public R2 bucket.
281
- */
282
- static publicUrlForObjectWithPreset(obj, bucket, presetName) {
283
- if (obj.r2Bucket !== 'koolbase-storage-public')
284
- return null;
285
- return KoolbaseStorage.publicUrlWithPreset({
286
- projectId: obj.projectId,
287
- presetName,
288
- bucket,
289
- path: obj.path,
290
- });
291
- }
292
- /**
293
- * Delete a file from a bucket.
294
- */
295
- async delete(bucket, path, forcePurge) {
296
- const url = forcePurge
297
- ? `${this.config.baseUrl}/v1/sdk/storage/object?force_purge=true`
298
- : `${this.config.baseUrl}/v1/sdk/storage/object`;
299
- const res = await fetch(url, {
300
- method: 'DELETE',
301
- headers: {
302
- ...(await this.buildHeaders()),
303
- 'Content-Type': 'application/json',
304
- },
305
- body: JSON.stringify({ bucket, path }),
306
- });
307
- if (res.status === 204)
308
- return;
309
- if (!res.ok) {
310
- throw await (0, storage_errors_1.koolbaseStorageErrorFromResponse)(res, 'Failed to delete file');
311
- }
312
- }
313
- /**
314
- * List all versions of a file path, newest-first. Returns a flat list
315
- * mixing the current row (with `isCurrent: true`) and all history
316
- * rows. Delete markers are included so callers can render the full
317
- * timeline; filter client-side to hide them if the UI only wants
318
- * restorable versions.
319
- *
320
- * Returns an empty array (not an error) when the path has no history
321
- * and no current row.
322
- */
323
- async listVersions(bucket, path) {
324
- const url = `${this.config.baseUrl}/v1/sdk/storage/object-versions` +
325
- `?bucket=${encodeURIComponent(bucket)}&path=${encodeURIComponent(path)}`;
326
- const res = await fetch(url, { headers: await this.buildHeaders() });
327
- if (!res.ok) {
328
- throw await (0, storage_errors_1.koolbaseStorageErrorFromResponse)(res, 'Failed to list versions');
329
- }
330
- const data = (await res.json());
331
- const list = Array.isArray(data.versions) ? data.versions : [];
332
- return list.map((v) => fromVersionJson(v));
333
- }
334
- /**
335
- * Fetch metadata for a single version by id. Works against both the
336
- * current row and any history row — the response's `isCurrent` tells
337
- * you which.
338
- */
339
- async getVersion(bucket, path, versionId) {
340
- const url = `${this.config.baseUrl}/v1/sdk/storage/object-versions/${encodeURIComponent(versionId)}` +
341
- `?bucket=${encodeURIComponent(bucket)}&path=${encodeURIComponent(path)}`;
342
- const res = await fetch(url, { headers: await this.buildHeaders() });
343
- if (!res.ok) {
344
- throw await (0, storage_errors_1.koolbaseStorageErrorFromResponse)(res, 'Failed to fetch version');
345
- }
346
- return fromVersionJson((await res.json()));
347
- }
348
- /**
349
- * Bring a history version back as the current version. The
350
- * previously-current row (if any) is snapshotted into history first,
351
- * so this operation is itself a versioned event you can undo. The
352
- * restored row gets a freshly-minted version_id; the target stays in
353
- * history at its original version_id.
354
- *
355
- * Throws if the bucket has versioning off, if the target is the
356
- * already-current version, or if the target is a delete marker.
357
- */
358
- async restoreVersion(bucket, path, versionId) {
359
- const url = `${this.config.baseUrl}/v1/sdk/storage/object-versions/${encodeURIComponent(versionId)}/restore` +
360
- `?bucket=${encodeURIComponent(bucket)}&path=${encodeURIComponent(path)}`;
361
- const res = await fetch(url, {
362
- method: 'POST',
363
- headers: await this.buildHeaders(),
364
- });
365
- if (!res.ok) {
366
- throw await (0, storage_errors_1.koolbaseStorageErrorFromResponse)(res, 'Failed to restore version');
367
- }
368
- return mapObjectFromServer(await res.json());
369
- }
370
- /**
371
- * Hard-remove a single history version — both the metadata row and
372
- * the .versions/ R2 bytes (or just the row, for delete markers).
373
- * Refuses to operate on the current version; use {@link delete} with
374
- * `forcePurge: true` to wipe everything for a path.
375
- */
376
- async purgeVersion(bucket, path, versionId) {
377
- const url = `${this.config.baseUrl}/v1/sdk/storage/object-versions/${encodeURIComponent(versionId)}` +
378
- `?bucket=${encodeURIComponent(bucket)}&path=${encodeURIComponent(path)}`;
379
- const res = await fetch(url, {
380
- method: 'DELETE',
381
- headers: await this.buildHeaders(),
382
- });
383
- if (res.status === 204)
384
- return;
385
- if (!res.ok) {
386
- throw await (0, storage_errors_1.koolbaseStorageErrorFromResponse)(res, 'Failed to purge version');
387
- }
388
- }
389
- }
390
- exports.KoolbaseStorage = KoolbaseStorage;
391
- /**
392
- * Maps the snake_case server JSON to the camelCase {@link KoolbaseObject}.
393
- * Defensive: missing or null `metadata` (older / non-Koolbase responses)
394
- * is coerced to an empty object so callers always see a typed
395
- * `Record<string, string>` rather than null.
396
- */
397
- function mapObjectFromServer(raw) {
398
- return {
399
- id: raw.id,
400
- projectId: raw.project_id,
401
- bucketId: raw.bucket_id,
402
- userId: raw.user_id ?? null,
403
- path: raw.path,
404
- size: raw.size ?? 0,
405
- contentType: raw.content_type ?? null,
406
- metadata: raw.metadata ?? {},
407
- r2Bucket: raw.r2_bucket ?? 'koolbase-storage',
408
- createdAt: raw.created_at,
409
- updatedAt: raw.updated_at,
410
- };
411
- }
412
- /**
413
- * Maps the snake_case server JSON of a version row to the camelCase
414
- * {@link KoolbaseObjectVersion}. Mirrors `fromObjectJson` shape.
415
- */
416
- function fromVersionJson(j) {
417
- const rawMeta = j.metadata;
418
- const metadata = {};
419
- if (rawMeta && typeof rawMeta === 'object') {
420
- for (const [k, v] of Object.entries(rawMeta)) {
421
- if (typeof v === 'string')
422
- metadata[k] = v;
423
- }
424
- }
425
- return {
426
- versionId: j.version_id ?? null,
427
- path: j.path,
428
- size: Number(j.size ?? 0),
429
- contentType: j.content_type ?? null,
430
- etag: j.etag ?? null,
431
- metadata,
432
- r2Bucket: j.r2_bucket ?? '',
433
- userId: j.user_id ?? null,
434
- isDeleteMarker: Boolean(j.is_delete_marker),
435
- isCurrent: Boolean(j.is_current),
436
- createdAt: j.created_at,
437
- };
438
- }
@@ -1,16 +0,0 @@
1
- import { KoolbaseConfig } from './types';
2
- type SyncCallback = () => void;
3
- export declare class SyncEngine {
4
- private config;
5
- private getUserId;
6
- private getToken;
7
- private onSyncComplete?;
8
- private unsubscribe?;
9
- private isSyncing;
10
- constructor(config: KoolbaseConfig, getUserId: () => string | null, getToken: () => Promise<string | null>, onSyncComplete?: SyncCallback);
11
- start(): void;
12
- stop(): void;
13
- flush(): Promise<void>;
14
- private executeWrite;
15
- }
16
- export {};
@@ -1,86 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.SyncEngine = void 0;
7
- const netinfo_1 = __importDefault(require("@react-native-community/netinfo"));
8
- const cache_store_1 = require("./cache-store");
9
- class SyncEngine {
10
- constructor(config, getUserId, getToken, onSyncComplete) {
11
- this.isSyncing = false;
12
- this.config = config;
13
- this.getUserId = getUserId;
14
- this.getToken = getToken;
15
- this.onSyncComplete = onSyncComplete;
16
- }
17
- start() {
18
- this.unsubscribe = netinfo_1.default.addEventListener(state => {
19
- if (state.isConnected && state.isInternetReachable !== false) {
20
- this.flush();
21
- }
22
- });
23
- }
24
- stop() {
25
- this.unsubscribe?.();
26
- }
27
- async flush() {
28
- if (this.isSyncing)
29
- return;
30
- const userId = this.getUserId();
31
- if (!userId)
32
- return;
33
- this.isSyncing = true;
34
- try {
35
- const queue = await (0, cache_store_1.getWriteQueue)(userId);
36
- if (queue.length === 0)
37
- return;
38
- for (const write of queue) {
39
- try {
40
- await this.executeWrite(write);
41
- await (0, cache_store_1.removeFromWriteQueue)(userId, write.id);
42
- }
43
- catch {
44
- await (0, cache_store_1.incrementWriteRetry)(userId, write.id);
45
- }
46
- }
47
- this.onSyncComplete?.();
48
- }
49
- finally {
50
- this.isSyncing = false;
51
- }
52
- }
53
- async executeWrite(write) {
54
- const token = await this.getToken();
55
- const headers = {
56
- 'Content-Type': 'application/json',
57
- 'x-api-key': this.config.publicKey,
58
- ...(token ? { Authorization: `Bearer ${token}` } : {}),
59
- };
60
- if (write.type === 'insert') {
61
- const res = await fetch(`${this.config.baseUrl}/v1/sdk/db/insert`, {
62
- method: 'POST',
63
- headers,
64
- body: JSON.stringify({ collection: write.collection, data: write.data }),
65
- });
66
- if (!res.ok)
67
- throw new Error(`Insert failed: ${res.status}`);
68
- }
69
- else if (write.type === 'update') {
70
- const res = await fetch(`${this.config.baseUrl}/v1/sdk/db/records/${write.recordId}`, {
71
- method: 'PATCH',
72
- headers,
73
- body: JSON.stringify({ data: write.data }),
74
- });
75
- if (!res.ok)
76
- throw new Error(`Update failed: ${res.status}`);
77
- }
78
- else if (write.type === 'delete') {
79
- const res = await fetch(`${this.config.baseUrl}/v1/sdk/db/records/${write.recordId}`, { method: 'DELETE', headers });
80
- if (!res.ok && res.status !== 204) {
81
- throw new Error(`Delete failed: ${res.status}`);
82
- }
83
- }
84
- }
85
- }
86
- exports.SyncEngine = SyncEngine;