@pol-studios/powersync 1.0.24 → 1.0.30
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 +0 -1
- package/dist/attachments/index.d.ts +1 -1
- package/dist/{background-sync-ChCXW-EV.d.ts → background-sync-CVR3PkFi.d.ts} +1 -1
- package/dist/{chunk-BGBQYQV3.js → chunk-BC2SRII2.js} +180 -299
- package/dist/chunk-BC2SRII2.js.map +1 -0
- package/dist/{chunk-YSTEESEG.js → chunk-C2ACBYBZ.js} +208 -11
- package/dist/chunk-C2ACBYBZ.js.map +1 -0
- package/dist/{chunk-24RDMMCL.js → chunk-FNYQFILT.js} +1 -1
- package/dist/chunk-FNYQFILT.js.map +1 -0
- package/dist/{chunk-YVX3A36I.js → chunk-JCGOZVWL.js} +406 -331
- package/dist/chunk-JCGOZVWL.js.map +1 -0
- package/dist/{chunk-WGHNIAF7.js → chunk-QREWE3NR.js} +2 -2
- package/dist/{chunk-TIFL2KWE.js → chunk-RBPWEOIV.js} +3 -3
- package/dist/{chunk-55DKCJV4.js → chunk-RE5HWLCB.js} +124 -13
- package/dist/chunk-RE5HWLCB.js.map +1 -0
- package/dist/connector/index.d.ts +4 -4
- package/dist/connector/index.js +1 -2
- package/dist/core/index.d.ts +2 -2
- package/dist/generator/cli.js +6 -1
- package/dist/generator/index.d.ts +1 -0
- package/dist/generator/index.js +9 -1
- package/dist/generator/index.js.map +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.js +27 -17
- package/dist/index.native.d.ts +5 -5
- package/dist/index.native.js +27 -17
- package/dist/index.web.d.ts +5 -5
- package/dist/index.web.js +27 -17
- package/dist/maintenance/index.d.ts +2 -2
- package/dist/maintenance/index.js +2 -2
- package/dist/platform/index.d.ts +1 -1
- package/dist/platform/index.native.d.ts +1 -1
- package/dist/platform/index.web.d.ts +1 -1
- package/dist/provider/index.d.ts +188 -28
- package/dist/provider/index.js +17 -7
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.js +3 -3
- package/dist/storage/index.d.ts +1 -1
- package/dist/storage/index.native.d.ts +1 -1
- package/dist/storage/index.web.d.ts +1 -1
- package/dist/{supabase-connector-D2oIl2t8.d.ts → supabase-connector-C4YpH_l3.d.ts} +23 -25
- package/dist/sync/index.d.ts +42 -5
- package/dist/sync/index.js +2 -2
- package/dist/{types-DiBvmGEi.d.ts → types-CpM2_LhU.d.ts} +17 -24
- package/dist/{types-CDqWh56B.d.ts → types-Dv1uf0LZ.d.ts} +16 -1
- package/package.json +2 -2
- package/dist/chunk-24RDMMCL.js.map +0 -1
- package/dist/chunk-55DKCJV4.js.map +0 -1
- package/dist/chunk-BGBQYQV3.js.map +0 -1
- package/dist/chunk-YSTEESEG.js.map +0 -1
- package/dist/chunk-YVX3A36I.js.map +0 -1
- /package/dist/{chunk-WGHNIAF7.js.map → chunk-QREWE3NR.js.map} +0 -0
- /package/dist/{chunk-TIFL2KWE.js.map → chunk-RBPWEOIV.js.map} +0 -0
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ export { ATTACHMENT_TABLE, AbstractAttachmentQueue, AttachmentState, AttachmentT
|
|
|
5
5
|
import { PlatformAdapter, LoggerAdapter } from '../platform/index.js';
|
|
6
6
|
import { AbstractPowerSyncDatabase } from '@powersync/common';
|
|
7
7
|
export { AbstractPowerSyncDatabase as PowerSyncDBInterface } from '@powersync/common';
|
|
8
|
-
import '../types-
|
|
8
|
+
import '../types-Dv1uf0LZ.js';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* POL Storage Adapter
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as SyncStatus, S as SyncMode, e as SyncMetrics, b as ConnectionHealth, f as SyncError } from './types-
|
|
1
|
+
import { a as SyncStatus, S as SyncMode, e as SyncMetrics, b as ConnectionHealth, f as SyncError } from './types-Dv1uf0LZ.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Sync Module Types for @pol-studios/powersync
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
withExponentialBackoff
|
|
3
|
-
} from "./chunk-FV2HXEIY.js";
|
|
4
1
|
import {
|
|
5
2
|
classifySupabaseError,
|
|
6
|
-
extractHttpStatusCode
|
|
7
|
-
isRlsError
|
|
3
|
+
extractHttpStatusCode
|
|
8
4
|
} from "./chunk-I2AYMY5O.js";
|
|
9
5
|
|
|
10
6
|
// src/connector/types.ts
|
|
@@ -13,31 +9,20 @@ var DEFAULT_RETRY_CONFIG = {
|
|
|
13
9
|
transient: {
|
|
14
10
|
maxRetries: 3,
|
|
15
11
|
baseDelayMs: 1e3,
|
|
16
|
-
// 1 second initial delay
|
|
17
12
|
maxDelayMs: 4e3,
|
|
18
|
-
// 4 second cap
|
|
19
13
|
backoffMultiplier: 2
|
|
20
|
-
// 1s → 2s → 4s
|
|
21
14
|
},
|
|
22
15
|
permanent: {
|
|
23
16
|
maxRetries: 0,
|
|
24
|
-
// No retries - permanent errors won't succeed
|
|
25
17
|
baseDelayMs: 1e3,
|
|
26
|
-
// Irrelevant with 0 retries, but needed for type
|
|
27
18
|
maxDelayMs: 1e3,
|
|
28
|
-
// Irrelevant with 0 retries
|
|
29
19
|
backoffMultiplier: 1
|
|
30
|
-
// Irrelevant with 0 retries
|
|
31
20
|
},
|
|
32
21
|
rls: {
|
|
33
|
-
maxRetries:
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
maxDelayMs: 12e4,
|
|
38
|
-
// 2 minutes max delay
|
|
39
|
-
backoffMultiplier: 2
|
|
40
|
-
// 30s → 60s → 120s → 120s → 120s
|
|
22
|
+
maxRetries: 0,
|
|
23
|
+
baseDelayMs: 1e3,
|
|
24
|
+
maxDelayMs: 1e3,
|
|
25
|
+
backoffMultiplier: 1
|
|
41
26
|
}
|
|
42
27
|
};
|
|
43
28
|
|
|
@@ -377,8 +362,6 @@ var SupabaseConnector = class _SupabaseConnector {
|
|
|
377
362
|
versionColumnPromises = /* @__PURE__ */ new Map();
|
|
378
363
|
// Flag to track if connector has been destroyed
|
|
379
364
|
isDestroyed = false;
|
|
380
|
-
// Retry configuration
|
|
381
|
-
retryConfig;
|
|
382
365
|
// Track completion failures for circuit breaker logic
|
|
383
366
|
// Maps transaction fingerprint (hash of entry IDs) to failure tracking info
|
|
384
367
|
completionFailures = /* @__PURE__ */ new Map();
|
|
@@ -386,13 +369,6 @@ var SupabaseConnector = class _SupabaseConnector {
|
|
|
386
369
|
static COMPLETION_EXTENDED_TIMEOUT_MS = 6e4;
|
|
387
370
|
// 60s timeout for retry
|
|
388
371
|
static MAX_STORED_RESOLUTIONS = 100;
|
|
389
|
-
autoRetryPaused = false;
|
|
390
|
-
// Per-entry cooldown tracking for failed operations
|
|
391
|
-
// Maps entry key (table:id) to the timestamp when it can be retried
|
|
392
|
-
entryCooldowns = /* @__PURE__ */ new Map();
|
|
393
|
-
static COOLDOWN_DURATION_MS = 6e4;
|
|
394
|
-
// 1 minute cooldown after exhausting retries
|
|
395
|
-
static MAX_ENTRY_COOLDOWNS = 200;
|
|
396
372
|
// Upload error middleware chain
|
|
397
373
|
uploadErrorMiddleware;
|
|
398
374
|
constructor(options) {
|
|
@@ -408,20 +384,6 @@ var SupabaseConnector = class _SupabaseConnector {
|
|
|
408
384
|
this.conflictDetection = options.conflictDetection;
|
|
409
385
|
this.conflictHandler = options.conflictHandler;
|
|
410
386
|
this.conflictBus = options.conflictBus;
|
|
411
|
-
this.retryConfig = {
|
|
412
|
-
transient: {
|
|
413
|
-
...DEFAULT_RETRY_CONFIG.transient,
|
|
414
|
-
...options.retryConfig?.transient
|
|
415
|
-
},
|
|
416
|
-
permanent: {
|
|
417
|
-
...DEFAULT_RETRY_CONFIG.permanent,
|
|
418
|
-
...options.retryConfig?.permanent
|
|
419
|
-
},
|
|
420
|
-
rls: {
|
|
421
|
-
...DEFAULT_RETRY_CONFIG.rls,
|
|
422
|
-
...options.retryConfig?.rls
|
|
423
|
-
}
|
|
424
|
-
};
|
|
425
387
|
this.uploadErrorMiddleware = options.uploadErrorMiddleware ?? [];
|
|
426
388
|
if (this.conflictBus) {
|
|
427
389
|
this.unsubscribeResolution = this.conflictBus.onResolution((table, recordId, resolution) => {
|
|
@@ -464,80 +426,46 @@ var SupabaseConnector = class _SupabaseConnector {
|
|
|
464
426
|
const sortedIds = entries.map((e) => `${e.table}:${e.id}`).sort();
|
|
465
427
|
return sortedIds.join("|");
|
|
466
428
|
}
|
|
467
|
-
// ───
|
|
429
|
+
// ─── Simplified Entry Processing ───────────────────────────────────────────
|
|
430
|
+
//
|
|
431
|
+
// Architecture:
|
|
432
|
+
// - NO internal retry loops - PowerSync SDK handles all retries naturally
|
|
433
|
+
// - Middleware decides once: success/discard/retry/fail_transaction
|
|
434
|
+
// - 'retry' = transient error, throw to let PowerSync retry on next sync cycle
|
|
435
|
+
// - 'fail_transaction' = permanent error, throw immediately with failure callback
|
|
436
|
+
// - 'discard' = silently skip via DiscardEntryError
|
|
437
|
+
// - 'success' = treat as completed, return normally
|
|
438
|
+
//
|
|
439
|
+
// This keeps error handling simple and lets the user configure middleware
|
|
440
|
+
// to decide what to do with each error type.
|
|
468
441
|
/**
|
|
469
|
-
*
|
|
470
|
-
* Use this when the user goes offline intentionally or wants manual control.
|
|
471
|
-
*/
|
|
472
|
-
pauseAutoRetry() {
|
|
473
|
-
this.autoRetryPaused = true;
|
|
474
|
-
if (__DEV__) {
|
|
475
|
-
console.log("[Connector] Auto-retry paused");
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
/**
|
|
479
|
-
* Resume automatic retry of failed uploads.
|
|
480
|
-
*/
|
|
481
|
-
resumeAutoRetry() {
|
|
482
|
-
this.autoRetryPaused = false;
|
|
483
|
-
if (__DEV__) {
|
|
484
|
-
console.log("[Connector] Auto-retry resumed");
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
// ─── Private Retry Logic ───────────────────────────────────────────────────
|
|
488
|
-
/**
|
|
489
|
-
* Process a single CRUD entry with exponential backoff retry.
|
|
490
|
-
*
|
|
491
|
-
* This method uses a two-phase approach:
|
|
492
|
-
* 1. First attempt - try the operation to classify the error type
|
|
493
|
-
* 2. Retry phase - use the appropriate config (transient vs permanent) based on classification
|
|
442
|
+
* Process a single CRUD entry once (no internal retries).
|
|
494
443
|
*
|
|
495
|
-
*
|
|
496
|
-
*
|
|
444
|
+
* On failure, middleware classifies the error:
|
|
445
|
+
* - 'success': Treat as completed (e.g., idempotent duplicate)
|
|
446
|
+
* - 'discard': Remove from queue silently
|
|
447
|
+
* - 'retry': Throw to let PowerSync retry on next sync cycle
|
|
448
|
+
* - 'fail_transaction': Throw TransactionAbortError immediately
|
|
449
|
+
* - 'continue': Throw original error (PowerSync will retry)
|
|
497
450
|
*
|
|
498
451
|
* @param entry - The CRUD entry to process
|
|
499
|
-
* @throws Error
|
|
452
|
+
* @throws Error for all errors (PowerSync will retry)
|
|
453
|
+
* @throws TransactionAbortError when middleware returns 'fail_transaction'
|
|
454
|
+
* @throws DiscardEntryError for discarded entries
|
|
500
455
|
*/
|
|
501
|
-
async
|
|
456
|
+
async processEntryOnce(entry) {
|
|
502
457
|
if (this.isDestroyed) {
|
|
503
458
|
throw new Error("Connector destroyed");
|
|
504
459
|
}
|
|
505
|
-
const entryKey = `${entry.table}:${entry.id}`;
|
|
506
|
-
const cooldownUntil = this.entryCooldowns.get(entryKey);
|
|
507
|
-
if (cooldownUntil) {
|
|
508
|
-
if (Date.now() >= cooldownUntil) {
|
|
509
|
-
this.entryCooldowns.delete(entryKey);
|
|
510
|
-
} else {
|
|
511
|
-
const remainingMs = cooldownUntil - Date.now();
|
|
512
|
-
if (__DEV__) {
|
|
513
|
-
console.log("[Connector] Entry in cooldown, skipping:", {
|
|
514
|
-
table: entry.table,
|
|
515
|
-
id: entry.id,
|
|
516
|
-
remainingSec: Math.round(remainingMs / 1e3)
|
|
517
|
-
});
|
|
518
|
-
}
|
|
519
|
-
throw new Error(`Entry in cooldown for ${Math.round(remainingMs / 1e3)}s`);
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
const classified = {
|
|
523
|
-
isPermanent: false,
|
|
524
|
-
pgCode: void 0,
|
|
525
|
-
userMessage: ""
|
|
526
|
-
};
|
|
527
|
-
let lastError;
|
|
528
460
|
try {
|
|
529
461
|
await this.processCrudEntry(entry);
|
|
530
|
-
this.entryCooldowns.delete(entryKey);
|
|
531
462
|
return;
|
|
532
463
|
} catch (error) {
|
|
533
|
-
lastError = error instanceof Error ? error : new Error(String(error));
|
|
534
464
|
const classifiedError = classifySupabaseError(error);
|
|
535
|
-
|
|
536
|
-
classified.pgCode = classifiedError.pgCode;
|
|
537
|
-
classified.userMessage = classifiedError.userMessage;
|
|
465
|
+
const errorObj = error instanceof Error ? error : new Error(String(error));
|
|
538
466
|
if (isAuthError(error)) {
|
|
539
467
|
if (__DEV__) {
|
|
540
|
-
console.log("[Connector] Auth error detected, refreshing session
|
|
468
|
+
console.log("[Connector] Auth error detected, refreshing session:", {
|
|
541
469
|
table: entry.table,
|
|
542
470
|
op: entry.op,
|
|
543
471
|
id: entry.id
|
|
@@ -546,164 +474,99 @@ var SupabaseConnector = class _SupabaseConnector {
|
|
|
546
474
|
try {
|
|
547
475
|
await this.supabase.auth.refreshSession();
|
|
548
476
|
await this.processCrudEntry(entry);
|
|
549
|
-
this.entryCooldowns.delete(entryKey);
|
|
550
477
|
return;
|
|
551
478
|
} catch (retryError) {
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
classified.isPermanent = retriedClassification.isPermanent;
|
|
555
|
-
classified.pgCode = retriedClassification.pgCode;
|
|
556
|
-
classified.userMessage = retriedClassification.userMessage;
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
if (__DEV__) {
|
|
560
|
-
console.log("[Connector] Initial attempt failed, will retry with appropriate config:", {
|
|
561
|
-
table: entry.table,
|
|
562
|
-
op: entry.op,
|
|
563
|
-
id: entry.id,
|
|
564
|
-
isPermanent: classified.isPermanent,
|
|
565
|
-
pgCode: classified.pgCode,
|
|
566
|
-
userMessage: classified.userMessage
|
|
567
|
-
});
|
|
568
|
-
}
|
|
569
|
-
this.logger?.warn("[Connector] Initial attempt failed:", {
|
|
570
|
-
table: entry.table,
|
|
571
|
-
op: entry.op,
|
|
572
|
-
id: entry.id,
|
|
573
|
-
error: lastError.message,
|
|
574
|
-
isPermanent: classified.isPermanent
|
|
575
|
-
});
|
|
576
|
-
if (this.uploadErrorMiddleware.length > 0) {
|
|
577
|
-
const classifiedError2 = classifySupabaseError(error);
|
|
578
|
-
const schema = this.schemaRouter(entry.table);
|
|
579
|
-
const middlewareContext = {
|
|
580
|
-
entry,
|
|
581
|
-
error: lastError,
|
|
582
|
-
pgCode: classified.pgCode,
|
|
583
|
-
httpStatusCode: extractHttpStatusCode(error),
|
|
584
|
-
classified: classifiedError2,
|
|
585
|
-
originalError: error,
|
|
586
|
-
schema,
|
|
587
|
-
supabase: this.supabase
|
|
588
|
-
};
|
|
589
|
-
const middlewareResult = await runUploadErrorMiddleware(
|
|
590
|
-
middlewareContext,
|
|
591
|
-
this.uploadErrorMiddleware,
|
|
592
|
-
"continue"
|
|
593
|
-
// Default to continue if no middleware matches
|
|
594
|
-
);
|
|
595
|
-
if (__DEV__) {
|
|
596
|
-
console.log("[Connector] Upload error middleware result:", {
|
|
597
|
-
table: entry.table,
|
|
598
|
-
id: entry.id,
|
|
599
|
-
result: middlewareResult
|
|
600
|
-
});
|
|
601
|
-
}
|
|
602
|
-
switch (middlewareResult) {
|
|
603
|
-
case "success":
|
|
604
|
-
this.entryCooldowns.delete(entryKey);
|
|
605
|
-
this.logger?.info("[Connector] Entry treated as success by middleware:", {
|
|
606
|
-
table: entry.table,
|
|
607
|
-
id: entry.id,
|
|
608
|
-
pgCode: classified.pgCode
|
|
609
|
-
});
|
|
610
|
-
return;
|
|
611
|
-
case "discard":
|
|
612
|
-
this.entryCooldowns.delete(entryKey);
|
|
613
|
-
this.logger?.warn("[Connector] Entry discarded by middleware:", {
|
|
614
|
-
table: entry.table,
|
|
615
|
-
id: entry.id,
|
|
616
|
-
pgCode: classified.pgCode,
|
|
617
|
-
error: lastError.message
|
|
618
|
-
});
|
|
619
|
-
throw new DiscardEntryError(`Entry discarded by middleware: ${entry.table}:${entry.id} (${classified.pgCode || "unknown"})`);
|
|
620
|
-
case "retry":
|
|
621
|
-
break;
|
|
622
|
-
case "continue":
|
|
623
|
-
break;
|
|
624
|
-
case "fail_transaction":
|
|
625
|
-
this.logger?.error("[Connector] Transaction aborted by middleware:", {
|
|
626
|
-
table: entry.table,
|
|
627
|
-
id: entry.id,
|
|
628
|
-
pgCode: classified.pgCode,
|
|
629
|
-
error: lastError.message
|
|
630
|
-
});
|
|
631
|
-
throw new TransactionAbortError(`Transaction aborted by middleware: ${entry.table}:${entry.id}`, lastError);
|
|
479
|
+
const retryClassified = classifySupabaseError(retryError);
|
|
480
|
+
return this.handleEntryError(entry, retryError instanceof Error ? retryError : new Error(String(retryError)), retryClassified, retryError);
|
|
632
481
|
}
|
|
633
482
|
}
|
|
483
|
+
return this.handleEntryError(entry, errorObj, classifiedError, error);
|
|
634
484
|
}
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Handle an entry error by running middleware and deciding what to do.
|
|
488
|
+
*/
|
|
489
|
+
async handleEntryError(entry, error, classified, originalError) {
|
|
490
|
+
if (__DEV__) {
|
|
491
|
+
console.log("[Connector] Entry failed:", {
|
|
639
492
|
table: entry.table,
|
|
640
493
|
op: entry.op,
|
|
641
494
|
id: entry.id,
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
495
|
+
isPermanent: classified.isPermanent,
|
|
496
|
+
pgCode: classified.pgCode,
|
|
497
|
+
message: error.message
|
|
645
498
|
});
|
|
646
499
|
}
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
errorMessage: error.message
|
|
669
|
-
});
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
});
|
|
673
|
-
this.entryCooldowns.delete(entryKey);
|
|
674
|
-
} catch (error) {
|
|
675
|
-
const finalError = error instanceof Error ? error : new Error(String(error));
|
|
676
|
-
const category = classified.isPermanent ? "permanent" : classified.pgCode ? "transient" : "unknown";
|
|
500
|
+
this.logger?.warn("[Connector] Entry failed:", {
|
|
501
|
+
table: entry.table,
|
|
502
|
+
op: entry.op,
|
|
503
|
+
id: entry.id,
|
|
504
|
+
error: error.message,
|
|
505
|
+
isPermanent: classified.isPermanent
|
|
506
|
+
});
|
|
507
|
+
let middlewareResult = "continue";
|
|
508
|
+
if (this.uploadErrorMiddleware.length > 0) {
|
|
509
|
+
const schema = this.schemaRouter(entry.table);
|
|
510
|
+
const middlewareContext = {
|
|
511
|
+
entry,
|
|
512
|
+
error,
|
|
513
|
+
pgCode: classified.pgCode,
|
|
514
|
+
httpStatusCode: extractHttpStatusCode(originalError),
|
|
515
|
+
classified,
|
|
516
|
+
originalError,
|
|
517
|
+
schema,
|
|
518
|
+
supabase: this.supabase
|
|
519
|
+
};
|
|
520
|
+
middlewareResult = await runUploadErrorMiddleware(middlewareContext, this.uploadErrorMiddleware, "continue");
|
|
677
521
|
if (__DEV__) {
|
|
678
|
-
console.log("[Connector]
|
|
522
|
+
console.log("[Connector] Middleware result:", {
|
|
679
523
|
table: entry.table,
|
|
680
|
-
op: entry.op,
|
|
681
524
|
id: entry.id,
|
|
682
|
-
|
|
683
|
-
error: finalError.message
|
|
525
|
+
result: middlewareResult
|
|
684
526
|
});
|
|
685
527
|
}
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
error: finalError.message,
|
|
691
|
-
category
|
|
692
|
-
});
|
|
693
|
-
const cooldownMs = _SupabaseConnector.COOLDOWN_DURATION_MS;
|
|
694
|
-
if (this.entryCooldowns.size >= _SupabaseConnector.MAX_ENTRY_COOLDOWNS) {
|
|
695
|
-
const firstKey = this.entryCooldowns.keys().next().value;
|
|
696
|
-
if (firstKey) this.entryCooldowns.delete(firstKey);
|
|
697
|
-
}
|
|
698
|
-
this.entryCooldowns.set(entryKey, Date.now() + cooldownMs);
|
|
699
|
-
if (__DEV__) {
|
|
700
|
-
console.log("[Connector] Entry placed in cooldown:", {
|
|
528
|
+
}
|
|
529
|
+
switch (middlewareResult) {
|
|
530
|
+
case "success":
|
|
531
|
+
this.logger?.info("[Connector] Entry treated as success by middleware:", {
|
|
701
532
|
table: entry.table,
|
|
702
533
|
id: entry.id,
|
|
703
|
-
|
|
534
|
+
pgCode: classified.pgCode
|
|
704
535
|
});
|
|
705
|
-
|
|
706
|
-
|
|
536
|
+
return;
|
|
537
|
+
case "discard":
|
|
538
|
+
this.logger?.warn("[Connector] Entry discarded by middleware:", {
|
|
539
|
+
table: entry.table,
|
|
540
|
+
id: entry.id,
|
|
541
|
+
pgCode: classified.pgCode
|
|
542
|
+
});
|
|
543
|
+
throw new DiscardEntryError(`Entry discarded by middleware: ${entry.table}:${entry.id} (${classified.pgCode || "unknown"})`);
|
|
544
|
+
case "fail_transaction":
|
|
545
|
+
this.logger?.error("[Connector] Transaction aborted by middleware:", {
|
|
546
|
+
table: entry.table,
|
|
547
|
+
id: entry.id,
|
|
548
|
+
pgCode: classified.pgCode
|
|
549
|
+
});
|
|
550
|
+
throw new TransactionAbortError(`Transaction aborted by middleware: ${entry.table}:${entry.id}`, error);
|
|
551
|
+
case "retry":
|
|
552
|
+
if (__DEV__) {
|
|
553
|
+
console.log("[Connector] Middleware returned retry - throwing for PowerSync retry:", {
|
|
554
|
+
table: entry.table,
|
|
555
|
+
id: entry.id
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
throw error;
|
|
559
|
+
case "continue":
|
|
560
|
+
default:
|
|
561
|
+
if (__DEV__) {
|
|
562
|
+
console.log("[Connector] Error - throwing for PowerSync retry:", {
|
|
563
|
+
table: entry.table,
|
|
564
|
+
id: entry.id,
|
|
565
|
+
isPermanent: classified.isPermanent,
|
|
566
|
+
pgCode: classified.pgCode
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
throw error;
|
|
707
570
|
}
|
|
708
571
|
}
|
|
709
572
|
/**
|
|
@@ -951,17 +814,23 @@ var SupabaseConnector = class _SupabaseConnector {
|
|
|
951
814
|
return;
|
|
952
815
|
}
|
|
953
816
|
const successfulEntries = [];
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
817
|
+
try {
|
|
818
|
+
for (const entry of entriesToProcess) {
|
|
819
|
+
if (__DEV__) {
|
|
820
|
+
console.log("[Connector] Processing CRUD entry:", {
|
|
821
|
+
table: entry.table,
|
|
822
|
+
op: entry.op,
|
|
823
|
+
id: entry.id,
|
|
824
|
+
opData: entry.opData
|
|
825
|
+
});
|
|
826
|
+
}
|
|
827
|
+
await this.processEntryOnce(entry);
|
|
828
|
+
successfulEntries.push(entry);
|
|
962
829
|
}
|
|
963
|
-
|
|
964
|
-
|
|
830
|
+
} catch (error) {
|
|
831
|
+
const classified = classifySupabaseError(error);
|
|
832
|
+
this.onTransactionFailure?.(entriesToProcess, error instanceof Error ? error : new Error(String(error)), classified);
|
|
833
|
+
throw error;
|
|
965
834
|
}
|
|
966
835
|
await this.finalizeTransaction({
|
|
967
836
|
transaction,
|
|
@@ -1147,50 +1016,56 @@ var SupabaseConnector = class _SupabaseConnector {
|
|
|
1147
1016
|
}]))
|
|
1148
1017
|
});
|
|
1149
1018
|
}
|
|
1150
|
-
|
|
1151
|
-
const
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1019
|
+
try {
|
|
1020
|
+
for (const [table, entries] of entriesByTable) {
|
|
1021
|
+
const schema = this.schemaRouter(table);
|
|
1022
|
+
const putEntries = entries.filter((e) => e.op === "PUT" /* PUT */);
|
|
1023
|
+
const patchEntries = entries.filter((e) => e.op === "PATCH" /* PATCH */);
|
|
1024
|
+
const deleteEntries = entries.filter((e) => e.op === "DELETE" /* DELETE */);
|
|
1025
|
+
if (this.crudHandler) {
|
|
1026
|
+
for (const entry of entries) {
|
|
1027
|
+
try {
|
|
1028
|
+
await this.processEntryOnce(entry);
|
|
1029
|
+
successfulEntries.push(entry);
|
|
1030
|
+
} catch (error) {
|
|
1031
|
+
if (error instanceof DiscardEntryError) {
|
|
1032
|
+
discardedEntries.push(entry);
|
|
1033
|
+
continue;
|
|
1034
|
+
}
|
|
1035
|
+
throw error;
|
|
1164
1036
|
}
|
|
1165
|
-
throw error;
|
|
1166
1037
|
}
|
|
1038
|
+
continue;
|
|
1039
|
+
}
|
|
1040
|
+
if (putEntries.length > 0) {
|
|
1041
|
+
const {
|
|
1042
|
+
successful,
|
|
1043
|
+
discarded
|
|
1044
|
+
} = await this.processBatchedPuts(table, schema, putEntries);
|
|
1045
|
+
successfulEntries.push(...successful);
|
|
1046
|
+
discardedEntries.push(...discarded);
|
|
1047
|
+
}
|
|
1048
|
+
if (deleteEntries.length > 0) {
|
|
1049
|
+
const {
|
|
1050
|
+
successful,
|
|
1051
|
+
discarded
|
|
1052
|
+
} = await this.processBatchedDeletes(table, schema, deleteEntries);
|
|
1053
|
+
successfulEntries.push(...successful);
|
|
1054
|
+
discardedEntries.push(...discarded);
|
|
1055
|
+
}
|
|
1056
|
+
if (patchEntries.length > 0) {
|
|
1057
|
+
const {
|
|
1058
|
+
successful,
|
|
1059
|
+
discarded
|
|
1060
|
+
} = await this.processBatchedPatches(table, schema, patchEntries);
|
|
1061
|
+
successfulEntries.push(...successful);
|
|
1062
|
+
discardedEntries.push(...discarded);
|
|
1167
1063
|
}
|
|
1168
|
-
continue;
|
|
1169
|
-
}
|
|
1170
|
-
if (putEntries.length > 0) {
|
|
1171
|
-
const {
|
|
1172
|
-
successful,
|
|
1173
|
-
discarded
|
|
1174
|
-
} = await this.processBatchedPuts(table, schema, putEntries);
|
|
1175
|
-
successfulEntries.push(...successful);
|
|
1176
|
-
discardedEntries.push(...discarded);
|
|
1177
|
-
}
|
|
1178
|
-
if (deleteEntries.length > 0) {
|
|
1179
|
-
const {
|
|
1180
|
-
successful,
|
|
1181
|
-
discarded
|
|
1182
|
-
} = await this.processBatchedDeletes(table, schema, deleteEntries);
|
|
1183
|
-
successfulEntries.push(...successful);
|
|
1184
|
-
discardedEntries.push(...discarded);
|
|
1185
|
-
}
|
|
1186
|
-
if (patchEntries.length > 0) {
|
|
1187
|
-
const {
|
|
1188
|
-
successful,
|
|
1189
|
-
discarded
|
|
1190
|
-
} = await this.processBatchedPatches(table, schema, patchEntries);
|
|
1191
|
-
successfulEntries.push(...successful);
|
|
1192
|
-
discardedEntries.push(...discarded);
|
|
1193
1064
|
}
|
|
1065
|
+
} catch (error) {
|
|
1066
|
+
const classified = classifySupabaseError(error);
|
|
1067
|
+
this.onTransactionFailure?.(transaction.crud, error instanceof Error ? error : new Error(String(error)), classified);
|
|
1068
|
+
throw error;
|
|
1194
1069
|
}
|
|
1195
1070
|
await this.finalizeTransaction({
|
|
1196
1071
|
transaction,
|
|
@@ -1235,7 +1110,7 @@ var SupabaseConnector = class _SupabaseConnector {
|
|
|
1235
1110
|
}
|
|
1236
1111
|
for (const entry of entries) {
|
|
1237
1112
|
try {
|
|
1238
|
-
await this.
|
|
1113
|
+
await this.processEntryOnce(entry);
|
|
1239
1114
|
successful.push(entry);
|
|
1240
1115
|
} catch (e) {
|
|
1241
1116
|
if (e instanceof DiscardEntryError) {
|
|
@@ -1292,7 +1167,7 @@ var SupabaseConnector = class _SupabaseConnector {
|
|
|
1292
1167
|
}
|
|
1293
1168
|
for (const entry of entries) {
|
|
1294
1169
|
try {
|
|
1295
|
-
await this.
|
|
1170
|
+
await this.processEntryOnce(entry);
|
|
1296
1171
|
successful.push(entry);
|
|
1297
1172
|
} catch (e) {
|
|
1298
1173
|
if (e instanceof DiscardEntryError) {
|
|
@@ -1347,7 +1222,7 @@ var SupabaseConnector = class _SupabaseConnector {
|
|
|
1347
1222
|
}
|
|
1348
1223
|
const results = await Promise.all(batch.map(async (entry) => {
|
|
1349
1224
|
try {
|
|
1350
|
-
await this.
|
|
1225
|
+
await this.processEntryOnce(entry);
|
|
1351
1226
|
return {
|
|
1352
1227
|
status: "success",
|
|
1353
1228
|
entry
|
|
@@ -1497,7 +1372,9 @@ var SupabaseConnector = class _SupabaseConnector {
|
|
|
1497
1372
|
errorHint: upsertError.hint
|
|
1498
1373
|
});
|
|
1499
1374
|
}
|
|
1500
|
-
|
|
1375
|
+
const upsertErr = new Error(`Upsert failed for ${schema}.${table}: ${upsertError.message}`);
|
|
1376
|
+
upsertErr.code = upsertError.code;
|
|
1377
|
+
throw upsertErr;
|
|
1501
1378
|
}
|
|
1502
1379
|
if (__DEV__) {
|
|
1503
1380
|
console.log("[Connector] PUT/UPSERT SUCCESS:", {
|
|
@@ -1534,7 +1411,9 @@ var SupabaseConnector = class _SupabaseConnector {
|
|
|
1534
1411
|
errorHint: updateError.hint
|
|
1535
1412
|
});
|
|
1536
1413
|
}
|
|
1537
|
-
|
|
1414
|
+
const updateErr = new Error(`Update failed for ${schema}.${table}: ${updateError.message}`);
|
|
1415
|
+
updateErr.code = updateError.code;
|
|
1416
|
+
throw updateErr;
|
|
1538
1417
|
}
|
|
1539
1418
|
if (__DEV__) {
|
|
1540
1419
|
console.log("[Connector] PATCH/UPDATE SUCCESS:", {
|
|
@@ -1570,7 +1449,9 @@ var SupabaseConnector = class _SupabaseConnector {
|
|
|
1570
1449
|
errorHint: deleteError.hint
|
|
1571
1450
|
});
|
|
1572
1451
|
}
|
|
1573
|
-
|
|
1452
|
+
const deleteErr = new Error(`Delete failed for ${schema}.${table}: ${deleteError.message}`);
|
|
1453
|
+
deleteErr.code = deleteError.code;
|
|
1454
|
+
throw deleteErr;
|
|
1574
1455
|
}
|
|
1575
1456
|
if (__DEV__) {
|
|
1576
1457
|
console.log("[Connector] DELETE SUCCESS:", {
|
|
@@ -1607,4 +1488,4 @@ export {
|
|
|
1607
1488
|
getLocalVersion,
|
|
1608
1489
|
SupabaseConnector
|
|
1609
1490
|
};
|
|
1610
|
-
//# sourceMappingURL=chunk-
|
|
1491
|
+
//# sourceMappingURL=chunk-BC2SRII2.js.map
|