@stamprally/core 0.16.0 → 0.18.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 +6 -6
- package/dist/index.cjs +1349 -1021
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +74 -18
- package/dist/index.d.ts +74 -18
- package/dist/index.js +1347 -1022
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -117,6 +117,10 @@ interface Reward<TLocale extends string = string> {
|
|
|
117
117
|
readonly validUntil?: string;
|
|
118
118
|
readonly stockLimit?: number;
|
|
119
119
|
readonly userClaimLimit?: number;
|
|
120
|
+
/** Explicit primary inventory key. Defaults to the reward id. */
|
|
121
|
+
readonly stockKey?: string;
|
|
122
|
+
/** Optional second inventory bucket that must be decremented atomically. */
|
|
123
|
+
readonly secondaryStockKey?: string;
|
|
120
124
|
}
|
|
121
125
|
type PublicReward<TLocale extends string = string> = Omit<Reward<TLocale>, "digitalContentUrl" | "staffPasscode">;
|
|
122
126
|
interface AdminRallyConfig<TLocale extends string = string, TMeta extends Record<string, unknown> = Record<string, unknown>> {
|
|
@@ -332,11 +336,9 @@ declare function createClaimTicketNumber(rewardId: string, options?: ClaimTicket
|
|
|
332
336
|
declare function createUniqueClaimTicketNumber(rewardId: string, issuedAt: string): string;
|
|
333
337
|
declare function issueClaimTicketNumber(reward: Reward, currentState: RewardState, options?: ClaimTicketOptions): RewardState;
|
|
334
338
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
/** Resolves a server/local state conflict without mutating either input state. */
|
|
339
|
-
declare function resolveRallyStateConflict(serverState: UserRallyState, localState: UserRallyState, options?: MergeConflictOptions): UserRallyState;
|
|
339
|
+
type ConflictResolutionPolicy = "authoritative_replay";
|
|
340
|
+
/** Uses the server snapshot as the immutable replay baseline. */
|
|
341
|
+
declare function resolveRallyStateConflict(serverState: UserRallyState, _localState: UserRallyState): UserRallyState;
|
|
340
342
|
|
|
341
343
|
type RewardConsumeError = {
|
|
342
344
|
readonly code: "NOT_AVAILABLE" | "ALREADY_CONSUMED" | "OUT_OF_STOCK" | "REWARD_NOT_FOUND";
|
|
@@ -374,20 +376,23 @@ declare function processStamp(state: StampRallyState, config: AdminRallyConfig,
|
|
|
374
376
|
|
|
375
377
|
type QueueOperationStatus = "PENDING" | "IN_FLIGHT" | "ACCEPTED" | "REJECTED_PERMANENT" | "FAILED_RETRYABLE";
|
|
376
378
|
type OfflineQueueCapability = "indexeddb" | "localstorage" | "memory" | "custom";
|
|
379
|
+
type OfflineStorageCapability = OfflineQueueCapability | "volatile_single_tab";
|
|
377
380
|
type OfflineOperation = {
|
|
378
381
|
readonly kind: "checkIn";
|
|
379
382
|
readonly request: CheckInRequest;
|
|
383
|
+
readonly optimisticState?: UserRallyState;
|
|
380
384
|
readonly status?: QueueOperationStatus;
|
|
381
385
|
readonly attempts?: number;
|
|
382
386
|
} | {
|
|
383
387
|
readonly kind: "claimReward";
|
|
384
388
|
readonly request: ClaimRequest;
|
|
389
|
+
readonly optimisticState?: UserRallyState;
|
|
385
390
|
readonly status?: QueueOperationStatus;
|
|
386
391
|
readonly attempts?: number;
|
|
387
392
|
};
|
|
388
393
|
type OfflineResult = CheckInResult | ClaimResult | UserRallyState;
|
|
389
394
|
type SyncState = "idle" | "syncing" | "error";
|
|
390
|
-
type SyncConflictPolicy = "
|
|
395
|
+
type SyncConflictPolicy = "authoritative_replay";
|
|
391
396
|
interface OfflineConflictResult {
|
|
392
397
|
readonly conflict: true;
|
|
393
398
|
readonly localState: UserRallyState;
|
|
@@ -399,6 +404,12 @@ interface OfflineQueueStorage {
|
|
|
399
404
|
loadRejectedHistory?(key: string): Promise<ReadonlyArray<RejectedOperationHistoryEntry>>;
|
|
400
405
|
saveRejectedHistory?(key: string, history: ReadonlyArray<RejectedOperationHistoryEntry>): Promise<void>;
|
|
401
406
|
}
|
|
407
|
+
interface OfflineQueueCapabilityWarning {
|
|
408
|
+
readonly type: "STORAGE_CAPABILITY_WARNING";
|
|
409
|
+
readonly storageCapability: "volatile_single_tab" | "memory";
|
|
410
|
+
readonly isStoragePersistent: boolean;
|
|
411
|
+
readonly message: string;
|
|
412
|
+
}
|
|
402
413
|
interface OfflineQueueOptions {
|
|
403
414
|
readonly storage?: OfflineQueueStorage;
|
|
404
415
|
readonly storageLike?: {
|
|
@@ -412,8 +423,6 @@ interface OfflineQueueOptions {
|
|
|
412
423
|
/** User scope used by the default durable key. */
|
|
413
424
|
readonly userId?: string | null;
|
|
414
425
|
readonly databaseName?: string;
|
|
415
|
-
readonly conflictPolicy?: SyncConflictPolicy;
|
|
416
|
-
readonly onSyncConflict?: SyncConflictPolicy | ((context: OfflineConflict) => SyncConflictPolicy | Promise<SyncConflictPolicy>);
|
|
417
426
|
/** Enables storage-event/BroadcastChannel synchronization when browser APIs exist. */
|
|
418
427
|
readonly synchronizeInstances?: boolean;
|
|
419
428
|
readonly retryOptions?: SyncRetryOptions;
|
|
@@ -426,11 +435,6 @@ interface SyncRetryOptions {
|
|
|
426
435
|
readonly initialIntervalMs?: number;
|
|
427
436
|
readonly backoffMultiplier?: number;
|
|
428
437
|
}
|
|
429
|
-
interface OfflineConflict {
|
|
430
|
-
readonly operation: OfflineOperation;
|
|
431
|
-
readonly localState: UserRallyState;
|
|
432
|
-
readonly serverState: UserRallyState;
|
|
433
|
-
}
|
|
434
438
|
type OfflineSender = (operation: OfflineOperation) => Promise<OfflineResult | OfflineConflictResult | OfflineOperationResponse>;
|
|
435
439
|
type OfflineOperationStatus = QueueOperationStatus | "REJECTED" | "RETRYABLE_ERROR";
|
|
436
440
|
type OfflineOperationLifecycleStatus = QueueOperationStatus;
|
|
@@ -469,6 +473,9 @@ interface OfflineSyncResultEvent {
|
|
|
469
473
|
readonly state?: UserRallyState;
|
|
470
474
|
}
|
|
471
475
|
type OfflineSyncResultListener = (event: OfflineSyncResultEvent) => void | Promise<void>;
|
|
476
|
+
type OfflineQueueChangeListener = () => void;
|
|
477
|
+
/** Removes only an operation's optimistic changes without mutating its inputs. */
|
|
478
|
+
declare function rollbackOptimisticOperation(state: UserRallyState, operation: OfflineOperation): UserRallyState;
|
|
472
479
|
declare class MemoryQueueStorage implements OfflineQueueStorage {
|
|
473
480
|
#private;
|
|
474
481
|
load(key: string): Promise<ReadonlyArray<OfflineOperation>>;
|
|
@@ -496,14 +503,18 @@ declare class OfflineQueue {
|
|
|
496
503
|
get syncState(): SyncState;
|
|
497
504
|
get pendingCount(): number;
|
|
498
505
|
get queueCapability(): OfflineQueueCapability;
|
|
506
|
+
get storageCapability(): OfflineStorageCapability;
|
|
507
|
+
get isStoragePersistent(): boolean;
|
|
499
508
|
get rejectedHistory(): ReadonlyArray<RejectedOperationHistoryEntry>;
|
|
500
509
|
get error(): Error | null;
|
|
501
510
|
get operations(): ReadonlyArray<OfflineOperation>;
|
|
502
|
-
get conflictPolicy(): SyncConflictPolicy;
|
|
503
511
|
get storageKey(): string;
|
|
504
512
|
get rallyId(): string | undefined;
|
|
505
513
|
get userId(): string | null;
|
|
506
514
|
setSyncResultListener(listener: OfflineSyncResultListener | undefined): void;
|
|
515
|
+
setChangeListener(listener: OfflineQueueChangeListener | undefined): void;
|
|
516
|
+
setCapabilityWarningListener(listener: ((event: OfflineQueueCapabilityWarning) => void) | undefined): void;
|
|
517
|
+
setReplayConfig(config: AdminRallyConfig | PublicRallyConfig): void;
|
|
507
518
|
initialize(): Promise<void>;
|
|
508
519
|
/** Releases browser listeners when the queue is no longer used. */
|
|
509
520
|
dispose(): void;
|
|
@@ -512,8 +523,8 @@ declare class OfflineQueue {
|
|
|
512
523
|
switchUser(newUserId: string | null): Promise<void>;
|
|
513
524
|
setSender(sender: OfflineSender): void;
|
|
514
525
|
enqueue(operation: OfflineOperation): Promise<void>;
|
|
515
|
-
enqueueCheckIn(request: CheckInRequest): Promise<void>;
|
|
516
|
-
enqueueClaimReward(request: ClaimRequest): Promise<void>;
|
|
526
|
+
enqueueCheckIn(request: CheckInRequest, optimisticState?: UserRallyState): Promise<void>;
|
|
527
|
+
enqueueClaimReward(request: ClaimRequest, optimisticState?: UserRallyState): Promise<void>;
|
|
517
528
|
clear(): Promise<void>;
|
|
518
529
|
discardRejected(operationId: string): Promise<boolean>;
|
|
519
530
|
retryRejected(operationId: string): Promise<boolean>;
|
|
@@ -522,7 +533,6 @@ declare class OfflineQueue {
|
|
|
522
533
|
clearRejectedHistory(): Promise<void>;
|
|
523
534
|
sync(sender?: OfflineSender | undefined): Promise<void>;
|
|
524
535
|
retrySync(sender?: OfflineSender | undefined): Promise<void>;
|
|
525
|
-
resolveConflict(operation: OfflineOperation, localState: UserRallyState, serverState: UserRallyState): Promise<UserRallyState>;
|
|
526
536
|
}
|
|
527
537
|
|
|
528
538
|
interface StampStorage {
|
|
@@ -640,12 +650,37 @@ type ClientEvent = {
|
|
|
640
650
|
} | {
|
|
641
651
|
readonly type: "sync";
|
|
642
652
|
readonly state: UserRallyState;
|
|
653
|
+
} | {
|
|
654
|
+
readonly type: "syncLifecycle";
|
|
655
|
+
readonly event: SyncLifecycleEvent;
|
|
643
656
|
} | {
|
|
644
657
|
readonly type: "error";
|
|
645
658
|
readonly error: ClientError | OfflineOperationError;
|
|
646
659
|
};
|
|
647
660
|
type ClientListener = (state: UserRallyState) => void;
|
|
648
661
|
type ClientEventListener = (event: ClientEvent) => void;
|
|
662
|
+
type SyncLifecycleEvent = {
|
|
663
|
+
readonly type: "SYNC_STARTED";
|
|
664
|
+
} | {
|
|
665
|
+
readonly type: "OPERATION_ACCEPTED";
|
|
666
|
+
readonly operationId: string;
|
|
667
|
+
readonly resourceId: string;
|
|
668
|
+
} | {
|
|
669
|
+
readonly type: "OPERATION_ROLLED_BACK";
|
|
670
|
+
readonly operationId: string;
|
|
671
|
+
readonly resourceId: string;
|
|
672
|
+
readonly reason: string;
|
|
673
|
+
readonly errorCode: string;
|
|
674
|
+
} | {
|
|
675
|
+
readonly type: "OPERATION_RETRYABLE_ERROR";
|
|
676
|
+
readonly operationId: string;
|
|
677
|
+
readonly error: string;
|
|
678
|
+
} | {
|
|
679
|
+
readonly type: "SYNC_COMPLETED";
|
|
680
|
+
readonly totalProcessed: number;
|
|
681
|
+
readonly failedCount: number;
|
|
682
|
+
};
|
|
683
|
+
type SyncEventListener = (event: SyncLifecycleEvent) => void;
|
|
649
684
|
interface CheckInRequest {
|
|
650
685
|
readonly rallyId: string;
|
|
651
686
|
readonly userId: string | null;
|
|
@@ -697,11 +732,18 @@ declare class StampRallyClient {
|
|
|
697
732
|
get syncState(): SyncState;
|
|
698
733
|
get pendingCount(): number;
|
|
699
734
|
get rejectedHistory(): ReadonlyArray<RejectedOperationHistoryEntry>;
|
|
735
|
+
getSyncRevision(): number;
|
|
700
736
|
get queueCapability(): OfflineQueueCapability;
|
|
737
|
+
get storageCapability(): OfflineStorageCapability;
|
|
738
|
+
get isStoragePersistent(): boolean;
|
|
701
739
|
discardRejected(operationId: string): Promise<boolean>;
|
|
702
740
|
retryRejected(operationId: string): Promise<boolean>;
|
|
741
|
+
dismissRejectedOperation(operationId: string): Promise<boolean>;
|
|
742
|
+
retryOperation(operationId: string): Promise<boolean>;
|
|
703
743
|
subscribe(listener: ClientListener): () => void;
|
|
704
744
|
subscribeEvents(listener: ClientEventListener): () => void;
|
|
745
|
+
subscribeSyncEvents(listener: SyncEventListener): () => void;
|
|
746
|
+
subscribeSyncState(listener: () => void): () => void;
|
|
705
747
|
init(): Promise<UserRallyState>;
|
|
706
748
|
initialize(): Promise<UserRallyState>;
|
|
707
749
|
switchUser(newUserId: string | null): Promise<UserRallyState>;
|
|
@@ -715,6 +757,20 @@ declare class StampRallyClient {
|
|
|
715
757
|
restore(state: UserRallyState): Promise<UserRallyState>;
|
|
716
758
|
}
|
|
717
759
|
|
|
760
|
+
interface RebuildUserStateOptions {
|
|
761
|
+
readonly baseline: UserRallyState;
|
|
762
|
+
readonly operations: ReadonlyArray<OfflineOperation>;
|
|
763
|
+
readonly config?: AdminRallyConfig | PublicRallyConfig;
|
|
764
|
+
}
|
|
765
|
+
interface RebuildUserStateResult {
|
|
766
|
+
readonly state: UserRallyState;
|
|
767
|
+
readonly rejectedOperationIds: ReadonlyArray<string>;
|
|
768
|
+
}
|
|
769
|
+
/** Replays the durable operation log on top of a server-confirmed baseline. */
|
|
770
|
+
declare function rebuildUserStateFromLog(baseline: UserRallyState, operations: ReadonlyArray<OfflineOperation>, config?: AdminRallyConfig | PublicRallyConfig): UserRallyState;
|
|
771
|
+
declare function rebuildUserStateFromLog(options: RebuildUserStateOptions): UserRallyState;
|
|
772
|
+
declare function rebuildUserStateLog(baseline: UserRallyState, operations: ReadonlyArray<OfflineOperation>, config?: AdminRallyConfig | PublicRallyConfig): RebuildUserStateResult;
|
|
773
|
+
|
|
718
774
|
type SecureTokenSecretKey = string | Uint8Array;
|
|
719
775
|
interface SecureTokenOptions {
|
|
720
776
|
readonly encrypt?: boolean;
|
|
@@ -820,4 +876,4 @@ type SnapshotTokenVerification<T extends SnapshotTokenPayload = SnapshotTokenPay
|
|
|
820
876
|
declare function createSignedSnapshotToken<T extends SnapshotTokenPayload>(payload: T, secretKey: SnapshotSecretKey): Promise<string>;
|
|
821
877
|
declare function verifySnapshotToken<T extends SnapshotTokenPayload = SnapshotTokenPayload>(token: string, secretKey: SnapshotSecretKey, now?: number): Promise<SnapshotTokenVerification<T>>;
|
|
822
878
|
|
|
823
|
-
export { type AdminRallyConfig, type CheckInCondition, type CheckInOptions, type CheckInRequest, type CheckInResult, type CheckInSuccess, type ClaimOptions, type ClaimRequest, type ClaimResult, type ClaimSuccess, type ClaimTicketOptions, type ClientError, type ClientEvent, type ClientEventListener, type ClientListener, type ClientOptions, type CompositeConditionFailure, type ConditionMatch, type ConditionMismatch, ConfigValidationError, type ConsumeResult, type ConsumeRewardParams, type CustomValidationContext, type CustomValidator, DEFAULT_SHEET_THEME, type DetectorError, type DetectorErrorCode, type DetectorKind, type DetectorResult, type ExternalReference, type FontFamily, type GeoDetectorOptions, type GeoVerificationContext, MemoryQueueStorage as InMemoryOfflineQueueStorage, InMemoryStorage, IndexedDBAdapter, type IndexedDBAdapterOptions, type IndexedDBOfflineQueueOptions, IndexedDBOfflineQueueStorage, type InventoryAggregationMode, LocalStorageAdapter, type LocalStorageAdapterOptions, type LocalStorageFailureMode, type LocaleDictionary, type LocalizedString, type LocalizedText, type
|
|
879
|
+
export { type AdminRallyConfig, type CheckInCondition, type CheckInOptions, type CheckInRequest, type CheckInResult, type CheckInSuccess, type ClaimOptions, type ClaimRequest, type ClaimResult, type ClaimSuccess, type ClaimTicketOptions, type ClientError, type ClientEvent, type ClientEventListener, type ClientListener, type ClientOptions, type CompositeConditionFailure, type ConditionMatch, type ConditionMismatch, ConfigValidationError, type ConflictResolutionPolicy, type ConsumeResult, type ConsumeRewardParams, type CustomValidationContext, type CustomValidator, DEFAULT_SHEET_THEME, type DetectorError, type DetectorErrorCode, type DetectorKind, type DetectorResult, type ExternalReference, type FontFamily, type GeoDetectorOptions, type GeoVerificationContext, MemoryQueueStorage as InMemoryOfflineQueueStorage, InMemoryStorage, IndexedDBAdapter, type IndexedDBAdapterOptions, type IndexedDBOfflineQueueOptions, IndexedDBOfflineQueueStorage, type InventoryAggregationMode, LocalStorageAdapter, type LocalStorageAdapterOptions, type LocalStorageFailureMode, type LocaleDictionary, type LocalizedString, type LocalizedText, type NfcDetectorOptions, type NfcVerificationContext, type OfflineConflictResult, type OfflineOperation, type OfflineOperationError, type OfflineOperationLifecycleStatus, type OfflineOperationResponse, type OfflineOperationStatus, OfflineQueue, type OfflineQueueCapability, type OfflineQueueCapabilityWarning, type OfflineQueueChangeListener, type OfflineQueueOptions, type OfflineQueueStorage, type OfflineResult, type OfflineSender, type OfflineStorageCapability, type OfflineSyncResultEvent, type OfflineSyncResultListener, type ParseResult, type PasscodeCondition$1 as PasscodeCondition, type ProcessStampValue, type PublicCheckInCondition, type PublicConfigSafety, type PublicRallyConfig, type PublicReward, type PublicSpotItem, type QrDetectorOptions, type QrVerificationContext, type QueueOperationStatus, type RallyConfig, type RallyInventory, type RallyInventoryState, type RallySnapshot, type RebuildUserStateOptions, type RebuildUserStateResult, type RedemptionMethod, type RejectedOperation, type RejectedOperationHistoryEntry, type Result, type Reward, type RewardConsumeError, type RewardState, type RewardStatus, type RewardType, type RewardUnlockCondition, type SecureTokenError, type SecureTokenErrorCode, type SecureTokenOptions, type SecureTokenPayload, type SecureTokenSecretKey, type SecureTokenVerification, type SheetTheme, type SlotShape, type SnapshotSecretKey, type SnapshotTokenError, type SnapshotTokenErrorCode, type SnapshotTokenPayload, type SnapshotTokenVerification, type SpotItem, type SpotStatus, type StampError, StampRallyClient, type StampRallyProgress, type StampRallyState, type StampRecord, type StampStorage, StorageAdapterError, type StorageAdapterErrorCode, type StorageLike, type StorageOperation, type StorageWarningHandler, type SupportedLocale, type SyncAdapter, type SyncConflictPolicy, type SyncEventListener, type SyncLifecycleEvent, type SyncRetryOptions, type SyncState, THEME_PRESETS, type ThemePreset, type ThemePresetId, type UserRallyState, type ValidationError, type Validator, type VerificationContext, assertPublicConfig, calculateDistanceMeters, calculateProgress, consumeReward, createAnonymousSessionId, createClaimTicketNumber, createSecureToken, createSignedSnapshotToken, createUniqueClaimTicketNumber, evaluateCondition, evaluateConditionDetailed, evaluateSpotStatus, exportProgressToken, getCurrentGeoContext, getOrderedSpots, getSpotStatus, importProgressToken, isGeolocationSupported, isNfcSupported, isPublicConfig, isQrSupported, isRewardState, isStampRallyState, issueClaimTicketNumber, normalizePasscode, offlineOperationId, parseAdminConfig, parsePublicConfig, processStamp, readNfcContext, readQrContext, rebuildUserStateFromLog, rebuildUserStateLog, reconcileRewardStates, resolveLocalizedText, resolveRallyStateConflict, rollbackOptimisticOperation, safeParseAdminConfig, safeParsePublicConfig, sanitizeAdminConfig, storageKey, toLocalizedString, toPublicConfig, updateLocalizedField, validatePublicConfigSafety, validateRallyConfigRelations, verifyPasscode, verifySecureToken, verifySnapshotToken };
|
package/dist/index.d.ts
CHANGED
|
@@ -117,6 +117,10 @@ interface Reward<TLocale extends string = string> {
|
|
|
117
117
|
readonly validUntil?: string;
|
|
118
118
|
readonly stockLimit?: number;
|
|
119
119
|
readonly userClaimLimit?: number;
|
|
120
|
+
/** Explicit primary inventory key. Defaults to the reward id. */
|
|
121
|
+
readonly stockKey?: string;
|
|
122
|
+
/** Optional second inventory bucket that must be decremented atomically. */
|
|
123
|
+
readonly secondaryStockKey?: string;
|
|
120
124
|
}
|
|
121
125
|
type PublicReward<TLocale extends string = string> = Omit<Reward<TLocale>, "digitalContentUrl" | "staffPasscode">;
|
|
122
126
|
interface AdminRallyConfig<TLocale extends string = string, TMeta extends Record<string, unknown> = Record<string, unknown>> {
|
|
@@ -332,11 +336,9 @@ declare function createClaimTicketNumber(rewardId: string, options?: ClaimTicket
|
|
|
332
336
|
declare function createUniqueClaimTicketNumber(rewardId: string, issuedAt: string): string;
|
|
333
337
|
declare function issueClaimTicketNumber(reward: Reward, currentState: RewardState, options?: ClaimTicketOptions): RewardState;
|
|
334
338
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
/** Resolves a server/local state conflict without mutating either input state. */
|
|
339
|
-
declare function resolveRallyStateConflict(serverState: UserRallyState, localState: UserRallyState, options?: MergeConflictOptions): UserRallyState;
|
|
339
|
+
type ConflictResolutionPolicy = "authoritative_replay";
|
|
340
|
+
/** Uses the server snapshot as the immutable replay baseline. */
|
|
341
|
+
declare function resolveRallyStateConflict(serverState: UserRallyState, _localState: UserRallyState): UserRallyState;
|
|
340
342
|
|
|
341
343
|
type RewardConsumeError = {
|
|
342
344
|
readonly code: "NOT_AVAILABLE" | "ALREADY_CONSUMED" | "OUT_OF_STOCK" | "REWARD_NOT_FOUND";
|
|
@@ -374,20 +376,23 @@ declare function processStamp(state: StampRallyState, config: AdminRallyConfig,
|
|
|
374
376
|
|
|
375
377
|
type QueueOperationStatus = "PENDING" | "IN_FLIGHT" | "ACCEPTED" | "REJECTED_PERMANENT" | "FAILED_RETRYABLE";
|
|
376
378
|
type OfflineQueueCapability = "indexeddb" | "localstorage" | "memory" | "custom";
|
|
379
|
+
type OfflineStorageCapability = OfflineQueueCapability | "volatile_single_tab";
|
|
377
380
|
type OfflineOperation = {
|
|
378
381
|
readonly kind: "checkIn";
|
|
379
382
|
readonly request: CheckInRequest;
|
|
383
|
+
readonly optimisticState?: UserRallyState;
|
|
380
384
|
readonly status?: QueueOperationStatus;
|
|
381
385
|
readonly attempts?: number;
|
|
382
386
|
} | {
|
|
383
387
|
readonly kind: "claimReward";
|
|
384
388
|
readonly request: ClaimRequest;
|
|
389
|
+
readonly optimisticState?: UserRallyState;
|
|
385
390
|
readonly status?: QueueOperationStatus;
|
|
386
391
|
readonly attempts?: number;
|
|
387
392
|
};
|
|
388
393
|
type OfflineResult = CheckInResult | ClaimResult | UserRallyState;
|
|
389
394
|
type SyncState = "idle" | "syncing" | "error";
|
|
390
|
-
type SyncConflictPolicy = "
|
|
395
|
+
type SyncConflictPolicy = "authoritative_replay";
|
|
391
396
|
interface OfflineConflictResult {
|
|
392
397
|
readonly conflict: true;
|
|
393
398
|
readonly localState: UserRallyState;
|
|
@@ -399,6 +404,12 @@ interface OfflineQueueStorage {
|
|
|
399
404
|
loadRejectedHistory?(key: string): Promise<ReadonlyArray<RejectedOperationHistoryEntry>>;
|
|
400
405
|
saveRejectedHistory?(key: string, history: ReadonlyArray<RejectedOperationHistoryEntry>): Promise<void>;
|
|
401
406
|
}
|
|
407
|
+
interface OfflineQueueCapabilityWarning {
|
|
408
|
+
readonly type: "STORAGE_CAPABILITY_WARNING";
|
|
409
|
+
readonly storageCapability: "volatile_single_tab" | "memory";
|
|
410
|
+
readonly isStoragePersistent: boolean;
|
|
411
|
+
readonly message: string;
|
|
412
|
+
}
|
|
402
413
|
interface OfflineQueueOptions {
|
|
403
414
|
readonly storage?: OfflineQueueStorage;
|
|
404
415
|
readonly storageLike?: {
|
|
@@ -412,8 +423,6 @@ interface OfflineQueueOptions {
|
|
|
412
423
|
/** User scope used by the default durable key. */
|
|
413
424
|
readonly userId?: string | null;
|
|
414
425
|
readonly databaseName?: string;
|
|
415
|
-
readonly conflictPolicy?: SyncConflictPolicy;
|
|
416
|
-
readonly onSyncConflict?: SyncConflictPolicy | ((context: OfflineConflict) => SyncConflictPolicy | Promise<SyncConflictPolicy>);
|
|
417
426
|
/** Enables storage-event/BroadcastChannel synchronization when browser APIs exist. */
|
|
418
427
|
readonly synchronizeInstances?: boolean;
|
|
419
428
|
readonly retryOptions?: SyncRetryOptions;
|
|
@@ -426,11 +435,6 @@ interface SyncRetryOptions {
|
|
|
426
435
|
readonly initialIntervalMs?: number;
|
|
427
436
|
readonly backoffMultiplier?: number;
|
|
428
437
|
}
|
|
429
|
-
interface OfflineConflict {
|
|
430
|
-
readonly operation: OfflineOperation;
|
|
431
|
-
readonly localState: UserRallyState;
|
|
432
|
-
readonly serverState: UserRallyState;
|
|
433
|
-
}
|
|
434
438
|
type OfflineSender = (operation: OfflineOperation) => Promise<OfflineResult | OfflineConflictResult | OfflineOperationResponse>;
|
|
435
439
|
type OfflineOperationStatus = QueueOperationStatus | "REJECTED" | "RETRYABLE_ERROR";
|
|
436
440
|
type OfflineOperationLifecycleStatus = QueueOperationStatus;
|
|
@@ -469,6 +473,9 @@ interface OfflineSyncResultEvent {
|
|
|
469
473
|
readonly state?: UserRallyState;
|
|
470
474
|
}
|
|
471
475
|
type OfflineSyncResultListener = (event: OfflineSyncResultEvent) => void | Promise<void>;
|
|
476
|
+
type OfflineQueueChangeListener = () => void;
|
|
477
|
+
/** Removes only an operation's optimistic changes without mutating its inputs. */
|
|
478
|
+
declare function rollbackOptimisticOperation(state: UserRallyState, operation: OfflineOperation): UserRallyState;
|
|
472
479
|
declare class MemoryQueueStorage implements OfflineQueueStorage {
|
|
473
480
|
#private;
|
|
474
481
|
load(key: string): Promise<ReadonlyArray<OfflineOperation>>;
|
|
@@ -496,14 +503,18 @@ declare class OfflineQueue {
|
|
|
496
503
|
get syncState(): SyncState;
|
|
497
504
|
get pendingCount(): number;
|
|
498
505
|
get queueCapability(): OfflineQueueCapability;
|
|
506
|
+
get storageCapability(): OfflineStorageCapability;
|
|
507
|
+
get isStoragePersistent(): boolean;
|
|
499
508
|
get rejectedHistory(): ReadonlyArray<RejectedOperationHistoryEntry>;
|
|
500
509
|
get error(): Error | null;
|
|
501
510
|
get operations(): ReadonlyArray<OfflineOperation>;
|
|
502
|
-
get conflictPolicy(): SyncConflictPolicy;
|
|
503
511
|
get storageKey(): string;
|
|
504
512
|
get rallyId(): string | undefined;
|
|
505
513
|
get userId(): string | null;
|
|
506
514
|
setSyncResultListener(listener: OfflineSyncResultListener | undefined): void;
|
|
515
|
+
setChangeListener(listener: OfflineQueueChangeListener | undefined): void;
|
|
516
|
+
setCapabilityWarningListener(listener: ((event: OfflineQueueCapabilityWarning) => void) | undefined): void;
|
|
517
|
+
setReplayConfig(config: AdminRallyConfig | PublicRallyConfig): void;
|
|
507
518
|
initialize(): Promise<void>;
|
|
508
519
|
/** Releases browser listeners when the queue is no longer used. */
|
|
509
520
|
dispose(): void;
|
|
@@ -512,8 +523,8 @@ declare class OfflineQueue {
|
|
|
512
523
|
switchUser(newUserId: string | null): Promise<void>;
|
|
513
524
|
setSender(sender: OfflineSender): void;
|
|
514
525
|
enqueue(operation: OfflineOperation): Promise<void>;
|
|
515
|
-
enqueueCheckIn(request: CheckInRequest): Promise<void>;
|
|
516
|
-
enqueueClaimReward(request: ClaimRequest): Promise<void>;
|
|
526
|
+
enqueueCheckIn(request: CheckInRequest, optimisticState?: UserRallyState): Promise<void>;
|
|
527
|
+
enqueueClaimReward(request: ClaimRequest, optimisticState?: UserRallyState): Promise<void>;
|
|
517
528
|
clear(): Promise<void>;
|
|
518
529
|
discardRejected(operationId: string): Promise<boolean>;
|
|
519
530
|
retryRejected(operationId: string): Promise<boolean>;
|
|
@@ -522,7 +533,6 @@ declare class OfflineQueue {
|
|
|
522
533
|
clearRejectedHistory(): Promise<void>;
|
|
523
534
|
sync(sender?: OfflineSender | undefined): Promise<void>;
|
|
524
535
|
retrySync(sender?: OfflineSender | undefined): Promise<void>;
|
|
525
|
-
resolveConflict(operation: OfflineOperation, localState: UserRallyState, serverState: UserRallyState): Promise<UserRallyState>;
|
|
526
536
|
}
|
|
527
537
|
|
|
528
538
|
interface StampStorage {
|
|
@@ -640,12 +650,37 @@ type ClientEvent = {
|
|
|
640
650
|
} | {
|
|
641
651
|
readonly type: "sync";
|
|
642
652
|
readonly state: UserRallyState;
|
|
653
|
+
} | {
|
|
654
|
+
readonly type: "syncLifecycle";
|
|
655
|
+
readonly event: SyncLifecycleEvent;
|
|
643
656
|
} | {
|
|
644
657
|
readonly type: "error";
|
|
645
658
|
readonly error: ClientError | OfflineOperationError;
|
|
646
659
|
};
|
|
647
660
|
type ClientListener = (state: UserRallyState) => void;
|
|
648
661
|
type ClientEventListener = (event: ClientEvent) => void;
|
|
662
|
+
type SyncLifecycleEvent = {
|
|
663
|
+
readonly type: "SYNC_STARTED";
|
|
664
|
+
} | {
|
|
665
|
+
readonly type: "OPERATION_ACCEPTED";
|
|
666
|
+
readonly operationId: string;
|
|
667
|
+
readonly resourceId: string;
|
|
668
|
+
} | {
|
|
669
|
+
readonly type: "OPERATION_ROLLED_BACK";
|
|
670
|
+
readonly operationId: string;
|
|
671
|
+
readonly resourceId: string;
|
|
672
|
+
readonly reason: string;
|
|
673
|
+
readonly errorCode: string;
|
|
674
|
+
} | {
|
|
675
|
+
readonly type: "OPERATION_RETRYABLE_ERROR";
|
|
676
|
+
readonly operationId: string;
|
|
677
|
+
readonly error: string;
|
|
678
|
+
} | {
|
|
679
|
+
readonly type: "SYNC_COMPLETED";
|
|
680
|
+
readonly totalProcessed: number;
|
|
681
|
+
readonly failedCount: number;
|
|
682
|
+
};
|
|
683
|
+
type SyncEventListener = (event: SyncLifecycleEvent) => void;
|
|
649
684
|
interface CheckInRequest {
|
|
650
685
|
readonly rallyId: string;
|
|
651
686
|
readonly userId: string | null;
|
|
@@ -697,11 +732,18 @@ declare class StampRallyClient {
|
|
|
697
732
|
get syncState(): SyncState;
|
|
698
733
|
get pendingCount(): number;
|
|
699
734
|
get rejectedHistory(): ReadonlyArray<RejectedOperationHistoryEntry>;
|
|
735
|
+
getSyncRevision(): number;
|
|
700
736
|
get queueCapability(): OfflineQueueCapability;
|
|
737
|
+
get storageCapability(): OfflineStorageCapability;
|
|
738
|
+
get isStoragePersistent(): boolean;
|
|
701
739
|
discardRejected(operationId: string): Promise<boolean>;
|
|
702
740
|
retryRejected(operationId: string): Promise<boolean>;
|
|
741
|
+
dismissRejectedOperation(operationId: string): Promise<boolean>;
|
|
742
|
+
retryOperation(operationId: string): Promise<boolean>;
|
|
703
743
|
subscribe(listener: ClientListener): () => void;
|
|
704
744
|
subscribeEvents(listener: ClientEventListener): () => void;
|
|
745
|
+
subscribeSyncEvents(listener: SyncEventListener): () => void;
|
|
746
|
+
subscribeSyncState(listener: () => void): () => void;
|
|
705
747
|
init(): Promise<UserRallyState>;
|
|
706
748
|
initialize(): Promise<UserRallyState>;
|
|
707
749
|
switchUser(newUserId: string | null): Promise<UserRallyState>;
|
|
@@ -715,6 +757,20 @@ declare class StampRallyClient {
|
|
|
715
757
|
restore(state: UserRallyState): Promise<UserRallyState>;
|
|
716
758
|
}
|
|
717
759
|
|
|
760
|
+
interface RebuildUserStateOptions {
|
|
761
|
+
readonly baseline: UserRallyState;
|
|
762
|
+
readonly operations: ReadonlyArray<OfflineOperation>;
|
|
763
|
+
readonly config?: AdminRallyConfig | PublicRallyConfig;
|
|
764
|
+
}
|
|
765
|
+
interface RebuildUserStateResult {
|
|
766
|
+
readonly state: UserRallyState;
|
|
767
|
+
readonly rejectedOperationIds: ReadonlyArray<string>;
|
|
768
|
+
}
|
|
769
|
+
/** Replays the durable operation log on top of a server-confirmed baseline. */
|
|
770
|
+
declare function rebuildUserStateFromLog(baseline: UserRallyState, operations: ReadonlyArray<OfflineOperation>, config?: AdminRallyConfig | PublicRallyConfig): UserRallyState;
|
|
771
|
+
declare function rebuildUserStateFromLog(options: RebuildUserStateOptions): UserRallyState;
|
|
772
|
+
declare function rebuildUserStateLog(baseline: UserRallyState, operations: ReadonlyArray<OfflineOperation>, config?: AdminRallyConfig | PublicRallyConfig): RebuildUserStateResult;
|
|
773
|
+
|
|
718
774
|
type SecureTokenSecretKey = string | Uint8Array;
|
|
719
775
|
interface SecureTokenOptions {
|
|
720
776
|
readonly encrypt?: boolean;
|
|
@@ -820,4 +876,4 @@ type SnapshotTokenVerification<T extends SnapshotTokenPayload = SnapshotTokenPay
|
|
|
820
876
|
declare function createSignedSnapshotToken<T extends SnapshotTokenPayload>(payload: T, secretKey: SnapshotSecretKey): Promise<string>;
|
|
821
877
|
declare function verifySnapshotToken<T extends SnapshotTokenPayload = SnapshotTokenPayload>(token: string, secretKey: SnapshotSecretKey, now?: number): Promise<SnapshotTokenVerification<T>>;
|
|
822
878
|
|
|
823
|
-
export { type AdminRallyConfig, type CheckInCondition, type CheckInOptions, type CheckInRequest, type CheckInResult, type CheckInSuccess, type ClaimOptions, type ClaimRequest, type ClaimResult, type ClaimSuccess, type ClaimTicketOptions, type ClientError, type ClientEvent, type ClientEventListener, type ClientListener, type ClientOptions, type CompositeConditionFailure, type ConditionMatch, type ConditionMismatch, ConfigValidationError, type ConsumeResult, type ConsumeRewardParams, type CustomValidationContext, type CustomValidator, DEFAULT_SHEET_THEME, type DetectorError, type DetectorErrorCode, type DetectorKind, type DetectorResult, type ExternalReference, type FontFamily, type GeoDetectorOptions, type GeoVerificationContext, MemoryQueueStorage as InMemoryOfflineQueueStorage, InMemoryStorage, IndexedDBAdapter, type IndexedDBAdapterOptions, type IndexedDBOfflineQueueOptions, IndexedDBOfflineQueueStorage, type InventoryAggregationMode, LocalStorageAdapter, type LocalStorageAdapterOptions, type LocalStorageFailureMode, type LocaleDictionary, type LocalizedString, type LocalizedText, type
|
|
879
|
+
export { type AdminRallyConfig, type CheckInCondition, type CheckInOptions, type CheckInRequest, type CheckInResult, type CheckInSuccess, type ClaimOptions, type ClaimRequest, type ClaimResult, type ClaimSuccess, type ClaimTicketOptions, type ClientError, type ClientEvent, type ClientEventListener, type ClientListener, type ClientOptions, type CompositeConditionFailure, type ConditionMatch, type ConditionMismatch, ConfigValidationError, type ConflictResolutionPolicy, type ConsumeResult, type ConsumeRewardParams, type CustomValidationContext, type CustomValidator, DEFAULT_SHEET_THEME, type DetectorError, type DetectorErrorCode, type DetectorKind, type DetectorResult, type ExternalReference, type FontFamily, type GeoDetectorOptions, type GeoVerificationContext, MemoryQueueStorage as InMemoryOfflineQueueStorage, InMemoryStorage, IndexedDBAdapter, type IndexedDBAdapterOptions, type IndexedDBOfflineQueueOptions, IndexedDBOfflineQueueStorage, type InventoryAggregationMode, LocalStorageAdapter, type LocalStorageAdapterOptions, type LocalStorageFailureMode, type LocaleDictionary, type LocalizedString, type LocalizedText, type NfcDetectorOptions, type NfcVerificationContext, type OfflineConflictResult, type OfflineOperation, type OfflineOperationError, type OfflineOperationLifecycleStatus, type OfflineOperationResponse, type OfflineOperationStatus, OfflineQueue, type OfflineQueueCapability, type OfflineQueueCapabilityWarning, type OfflineQueueChangeListener, type OfflineQueueOptions, type OfflineQueueStorage, type OfflineResult, type OfflineSender, type OfflineStorageCapability, type OfflineSyncResultEvent, type OfflineSyncResultListener, type ParseResult, type PasscodeCondition$1 as PasscodeCondition, type ProcessStampValue, type PublicCheckInCondition, type PublicConfigSafety, type PublicRallyConfig, type PublicReward, type PublicSpotItem, type QrDetectorOptions, type QrVerificationContext, type QueueOperationStatus, type RallyConfig, type RallyInventory, type RallyInventoryState, type RallySnapshot, type RebuildUserStateOptions, type RebuildUserStateResult, type RedemptionMethod, type RejectedOperation, type RejectedOperationHistoryEntry, type Result, type Reward, type RewardConsumeError, type RewardState, type RewardStatus, type RewardType, type RewardUnlockCondition, type SecureTokenError, type SecureTokenErrorCode, type SecureTokenOptions, type SecureTokenPayload, type SecureTokenSecretKey, type SecureTokenVerification, type SheetTheme, type SlotShape, type SnapshotSecretKey, type SnapshotTokenError, type SnapshotTokenErrorCode, type SnapshotTokenPayload, type SnapshotTokenVerification, type SpotItem, type SpotStatus, type StampError, StampRallyClient, type StampRallyProgress, type StampRallyState, type StampRecord, type StampStorage, StorageAdapterError, type StorageAdapterErrorCode, type StorageLike, type StorageOperation, type StorageWarningHandler, type SupportedLocale, type SyncAdapter, type SyncConflictPolicy, type SyncEventListener, type SyncLifecycleEvent, type SyncRetryOptions, type SyncState, THEME_PRESETS, type ThemePreset, type ThemePresetId, type UserRallyState, type ValidationError, type Validator, type VerificationContext, assertPublicConfig, calculateDistanceMeters, calculateProgress, consumeReward, createAnonymousSessionId, createClaimTicketNumber, createSecureToken, createSignedSnapshotToken, createUniqueClaimTicketNumber, evaluateCondition, evaluateConditionDetailed, evaluateSpotStatus, exportProgressToken, getCurrentGeoContext, getOrderedSpots, getSpotStatus, importProgressToken, isGeolocationSupported, isNfcSupported, isPublicConfig, isQrSupported, isRewardState, isStampRallyState, issueClaimTicketNumber, normalizePasscode, offlineOperationId, parseAdminConfig, parsePublicConfig, processStamp, readNfcContext, readQrContext, rebuildUserStateFromLog, rebuildUserStateLog, reconcileRewardStates, resolveLocalizedText, resolveRallyStateConflict, rollbackOptimisticOperation, safeParseAdminConfig, safeParsePublicConfig, sanitizeAdminConfig, storageKey, toLocalizedString, toPublicConfig, updateLocalizedField, validatePublicConfigSafety, validateRallyConfigRelations, verifyPasscode, verifySecureToken, verifySnapshotToken };
|