@stamprally/core 0.14.0 → 0.15.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/dist/index.d.cts CHANGED
@@ -97,6 +97,13 @@ type RewardUnlockCondition = {
97
97
  type RewardType = "digital" | "in_person";
98
98
  type RedemptionMethod = "manual_slide" | "staff_passcode" | "view_only" | "server_claim";
99
99
  type InventoryAggregationMode = "shared" | "per_reward";
100
+ type RallyInventory = Readonly<Record<string, number>> & {
101
+ readonly sharedStock?: number;
102
+ };
103
+ interface RallyInventoryState {
104
+ readonly sharedRemaining?: number;
105
+ readonly rewardRemaining?: Readonly<Record<string, number>>;
106
+ }
100
107
  interface Reward<TLocale extends string = string> {
101
108
  readonly id: string;
102
109
  readonly title: LocalizedText<TLocale>;
@@ -121,7 +128,7 @@ interface AdminRallyConfig<TLocale extends string = string, TMeta extends Record
121
128
  readonly spots: ReadonlyArray<SpotItem<TLocale, TMeta>>;
122
129
  readonly rewards: ReadonlyArray<Reward<TLocale>>;
123
130
  readonly staffPasscode?: string;
124
- readonly inventory?: Readonly<Record<string, number>>;
131
+ readonly inventory?: RallyInventory;
125
132
  /** How the optional top-level inventory limit is aggregated. */
126
133
  readonly inventoryMode?: InventoryAggregationMode;
127
134
  readonly serverMetadata?: Readonly<Record<string, unknown>>;
@@ -167,6 +174,7 @@ interface StampRallyState {
167
174
  readonly userId: string | null;
168
175
  readonly records: ReadonlyArray<StampRecord>;
169
176
  readonly rewards: ReadonlyArray<RewardState>;
177
+ readonly inventory?: RallyInventoryState;
170
178
  readonly updatedAt: string;
171
179
  }
172
180
  type UserRallyState = StampRallyState;
@@ -367,9 +375,13 @@ declare function processStamp(state: StampRallyState, config: AdminRallyConfig,
367
375
  type OfflineOperation = {
368
376
  readonly kind: "checkIn";
369
377
  readonly request: CheckInRequest;
378
+ readonly status?: OfflineOperationLifecycleStatus;
379
+ readonly attempts?: number;
370
380
  } | {
371
381
  readonly kind: "claimReward";
372
382
  readonly request: ClaimRequest;
383
+ readonly status?: OfflineOperationLifecycleStatus;
384
+ readonly attempts?: number;
373
385
  };
374
386
  type OfflineResult = CheckInResult | ClaimResult | UserRallyState;
375
387
  type SyncState = "idle" | "syncing" | "error";
@@ -400,6 +412,15 @@ interface OfflineQueueOptions {
400
412
  readonly onSyncConflict?: SyncConflictPolicy | ((context: OfflineConflict) => SyncConflictPolicy | Promise<SyncConflictPolicy>);
401
413
  /** Enables storage-event/BroadcastChannel synchronization when browser APIs exist. */
402
414
  readonly synchronizeInstances?: boolean;
415
+ readonly retryOptions?: SyncRetryOptions;
416
+ readonly retry?: SyncRetryOptions;
417
+ /** Alias accepted for callers that configure retry behavior at sync time. */
418
+ readonly syncRetryOptions?: SyncRetryOptions;
419
+ }
420
+ interface SyncRetryOptions {
421
+ readonly maxRetries?: number;
422
+ readonly initialIntervalMs?: number;
423
+ readonly backoffMultiplier?: number;
403
424
  }
404
425
  interface OfflineConflict {
405
426
  readonly operation: OfflineOperation;
@@ -407,7 +428,8 @@ interface OfflineConflict {
407
428
  readonly serverState: UserRallyState;
408
429
  }
409
430
  type OfflineSender = (operation: OfflineOperation) => Promise<OfflineResult | OfflineConflictResult | OfflineOperationResponse>;
410
- type OfflineOperationStatus = "ACCEPTED" | "REJECTED_PERMANENT" | "RETRYABLE_ERROR";
431
+ type OfflineOperationStatus = "PENDING" | "IN_FLIGHT" | "ACCEPTED" | "REJECTED" | "REJECTED_PERMANENT" | "RETRYABLE_ERROR";
432
+ type OfflineOperationLifecycleStatus = "PENDING" | "IN_FLIGHT" | "ACCEPTED" | "REJECTED";
411
433
  interface OfflineOperationError {
412
434
  readonly code: string;
413
435
  readonly message: string;
@@ -519,6 +541,7 @@ declare class InMemoryStorage implements StampStorage {
519
541
  remove(rallyId: string, userId: string | null): Promise<void>;
520
542
  }
521
543
  declare function storageKey(rallyId: string, userId: string | null): string;
544
+ declare function createAnonymousSessionId(storage?: StorageLike | null): string;
522
545
  interface LocalStorageAdapterOptions {
523
546
  readonly storage?: StorageLike | null;
524
547
  readonly keyPrefix?: string;
@@ -607,6 +630,7 @@ interface CheckInRequest {
607
630
  readonly idempotencyKey: string;
608
631
  readonly now: string;
609
632
  readonly state: UserRallyState;
633
+ readonly anonymousSessionId?: string;
610
634
  }
611
635
  interface ClaimRequest {
612
636
  readonly rallyId: string;
@@ -616,6 +640,7 @@ interface ClaimRequest {
616
640
  readonly now: string;
617
641
  readonly options: ClaimOptions;
618
642
  readonly state: UserRallyState;
643
+ readonly anonymousSessionId?: string;
619
644
  }
620
645
  interface SyncAdapter {
621
646
  readonly checkIn?: (request: CheckInRequest) => Promise<CheckInResult>;
@@ -624,6 +649,7 @@ interface SyncAdapter {
624
649
  readonly rallyId: string;
625
650
  readonly userId: string | null;
626
651
  readonly state: UserRallyState;
652
+ readonly anonymousSessionId?: string;
627
653
  }) => Promise<UserRallyState>;
628
654
  }
629
655
  interface ClientOptions {
@@ -633,6 +659,7 @@ interface ClientOptions {
633
659
  readonly customValidators?: Readonly<Record<string, Validator>>;
634
660
  readonly clock?: () => string;
635
661
  readonly userId?: string | null;
662
+ readonly anonymousSessionId?: string;
636
663
  readonly offlineQueue?: OfflineQueue;
637
664
  }
638
665
  type StorageOrOptions = StampStorage | ClientOptions;
@@ -642,6 +669,7 @@ declare class StampRallyClient {
642
669
  getConfig(): RallyConfig;
643
670
  getState(): UserRallyState | null;
644
671
  getUserId(): string | null;
672
+ getAnonymousSessionId(): string;
645
673
  get syncState(): SyncState;
646
674
  get pendingCount(): number;
647
675
  subscribe(listener: ClientListener): () => void;
@@ -764,4 +792,4 @@ type SnapshotTokenVerification<T extends SnapshotTokenPayload = SnapshotTokenPay
764
792
  declare function createSignedSnapshotToken<T extends SnapshotTokenPayload>(payload: T, secretKey: SnapshotSecretKey): Promise<string>;
765
793
  declare function verifySnapshotToken<T extends SnapshotTokenPayload = SnapshotTokenPayload>(token: string, secretKey: SnapshotSecretKey, now?: number): Promise<SnapshotTokenVerification<T>>;
766
794
 
767
- 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 MergeConflictOptions, type NfcDetectorOptions, type NfcVerificationContext, type OfflineConflict, type OfflineConflictResult, type OfflineOperation, type OfflineOperationError, type OfflineOperationResponse, type OfflineOperationStatus, OfflineQueue, type OfflineQueueOptions, type OfflineQueueStorage, type OfflineResult, type OfflineSender, 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 RallyConfig, type RallySnapshot, type RedemptionMethod, 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 SyncState, THEME_PRESETS, type ThemePreset, type ThemePresetId, type UserRallyState, type ValidationError, type Validator, type VerificationContext, assertPublicConfig, calculateDistanceMeters, calculateProgress, consumeReward, createClaimTicketNumber, createSecureToken, createSignedSnapshotToken, createUniqueClaimTicketNumber, evaluateCondition, evaluateConditionDetailed, evaluateSpotStatus, exportProgressToken, getCurrentGeoContext, getOrderedSpots, getSpotStatus, importProgressToken, isGeolocationSupported, isNfcSupported, isPublicConfig, isQrSupported, isRewardState, isStampRallyState, issueClaimTicketNumber, normalizePasscode, parseAdminConfig, parsePublicConfig, processStamp, readNfcContext, readQrContext, reconcileRewardStates, resolveLocalizedText, resolveRallyStateConflict, safeParseAdminConfig, safeParsePublicConfig, sanitizeAdminConfig, storageKey, toLocalizedString, toPublicConfig, updateLocalizedField, validatePublicConfigSafety, validateRallyConfigRelations, verifyPasscode, verifySecureToken, verifySnapshotToken };
795
+ 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 MergeConflictOptions, type NfcDetectorOptions, type NfcVerificationContext, type OfflineConflict, type OfflineConflictResult, type OfflineOperation, type OfflineOperationError, type OfflineOperationLifecycleStatus, type OfflineOperationResponse, type OfflineOperationStatus, OfflineQueue, type OfflineQueueOptions, type OfflineQueueStorage, type OfflineResult, type OfflineSender, 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 RallyConfig, type RallyInventory, type RallyInventoryState, type RallySnapshot, type RedemptionMethod, 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 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, parseAdminConfig, parsePublicConfig, processStamp, readNfcContext, readQrContext, reconcileRewardStates, resolveLocalizedText, resolveRallyStateConflict, safeParseAdminConfig, safeParsePublicConfig, sanitizeAdminConfig, storageKey, toLocalizedString, toPublicConfig, updateLocalizedField, validatePublicConfigSafety, validateRallyConfigRelations, verifyPasscode, verifySecureToken, verifySnapshotToken };
package/dist/index.d.ts CHANGED
@@ -97,6 +97,13 @@ type RewardUnlockCondition = {
97
97
  type RewardType = "digital" | "in_person";
98
98
  type RedemptionMethod = "manual_slide" | "staff_passcode" | "view_only" | "server_claim";
99
99
  type InventoryAggregationMode = "shared" | "per_reward";
100
+ type RallyInventory = Readonly<Record<string, number>> & {
101
+ readonly sharedStock?: number;
102
+ };
103
+ interface RallyInventoryState {
104
+ readonly sharedRemaining?: number;
105
+ readonly rewardRemaining?: Readonly<Record<string, number>>;
106
+ }
100
107
  interface Reward<TLocale extends string = string> {
101
108
  readonly id: string;
102
109
  readonly title: LocalizedText<TLocale>;
@@ -121,7 +128,7 @@ interface AdminRallyConfig<TLocale extends string = string, TMeta extends Record
121
128
  readonly spots: ReadonlyArray<SpotItem<TLocale, TMeta>>;
122
129
  readonly rewards: ReadonlyArray<Reward<TLocale>>;
123
130
  readonly staffPasscode?: string;
124
- readonly inventory?: Readonly<Record<string, number>>;
131
+ readonly inventory?: RallyInventory;
125
132
  /** How the optional top-level inventory limit is aggregated. */
126
133
  readonly inventoryMode?: InventoryAggregationMode;
127
134
  readonly serverMetadata?: Readonly<Record<string, unknown>>;
@@ -167,6 +174,7 @@ interface StampRallyState {
167
174
  readonly userId: string | null;
168
175
  readonly records: ReadonlyArray<StampRecord>;
169
176
  readonly rewards: ReadonlyArray<RewardState>;
177
+ readonly inventory?: RallyInventoryState;
170
178
  readonly updatedAt: string;
171
179
  }
172
180
  type UserRallyState = StampRallyState;
@@ -367,9 +375,13 @@ declare function processStamp(state: StampRallyState, config: AdminRallyConfig,
367
375
  type OfflineOperation = {
368
376
  readonly kind: "checkIn";
369
377
  readonly request: CheckInRequest;
378
+ readonly status?: OfflineOperationLifecycleStatus;
379
+ readonly attempts?: number;
370
380
  } | {
371
381
  readonly kind: "claimReward";
372
382
  readonly request: ClaimRequest;
383
+ readonly status?: OfflineOperationLifecycleStatus;
384
+ readonly attempts?: number;
373
385
  };
374
386
  type OfflineResult = CheckInResult | ClaimResult | UserRallyState;
375
387
  type SyncState = "idle" | "syncing" | "error";
@@ -400,6 +412,15 @@ interface OfflineQueueOptions {
400
412
  readonly onSyncConflict?: SyncConflictPolicy | ((context: OfflineConflict) => SyncConflictPolicy | Promise<SyncConflictPolicy>);
401
413
  /** Enables storage-event/BroadcastChannel synchronization when browser APIs exist. */
402
414
  readonly synchronizeInstances?: boolean;
415
+ readonly retryOptions?: SyncRetryOptions;
416
+ readonly retry?: SyncRetryOptions;
417
+ /** Alias accepted for callers that configure retry behavior at sync time. */
418
+ readonly syncRetryOptions?: SyncRetryOptions;
419
+ }
420
+ interface SyncRetryOptions {
421
+ readonly maxRetries?: number;
422
+ readonly initialIntervalMs?: number;
423
+ readonly backoffMultiplier?: number;
403
424
  }
404
425
  interface OfflineConflict {
405
426
  readonly operation: OfflineOperation;
@@ -407,7 +428,8 @@ interface OfflineConflict {
407
428
  readonly serverState: UserRallyState;
408
429
  }
409
430
  type OfflineSender = (operation: OfflineOperation) => Promise<OfflineResult | OfflineConflictResult | OfflineOperationResponse>;
410
- type OfflineOperationStatus = "ACCEPTED" | "REJECTED_PERMANENT" | "RETRYABLE_ERROR";
431
+ type OfflineOperationStatus = "PENDING" | "IN_FLIGHT" | "ACCEPTED" | "REJECTED" | "REJECTED_PERMANENT" | "RETRYABLE_ERROR";
432
+ type OfflineOperationLifecycleStatus = "PENDING" | "IN_FLIGHT" | "ACCEPTED" | "REJECTED";
411
433
  interface OfflineOperationError {
412
434
  readonly code: string;
413
435
  readonly message: string;
@@ -519,6 +541,7 @@ declare class InMemoryStorage implements StampStorage {
519
541
  remove(rallyId: string, userId: string | null): Promise<void>;
520
542
  }
521
543
  declare function storageKey(rallyId: string, userId: string | null): string;
544
+ declare function createAnonymousSessionId(storage?: StorageLike | null): string;
522
545
  interface LocalStorageAdapterOptions {
523
546
  readonly storage?: StorageLike | null;
524
547
  readonly keyPrefix?: string;
@@ -607,6 +630,7 @@ interface CheckInRequest {
607
630
  readonly idempotencyKey: string;
608
631
  readonly now: string;
609
632
  readonly state: UserRallyState;
633
+ readonly anonymousSessionId?: string;
610
634
  }
611
635
  interface ClaimRequest {
612
636
  readonly rallyId: string;
@@ -616,6 +640,7 @@ interface ClaimRequest {
616
640
  readonly now: string;
617
641
  readonly options: ClaimOptions;
618
642
  readonly state: UserRallyState;
643
+ readonly anonymousSessionId?: string;
619
644
  }
620
645
  interface SyncAdapter {
621
646
  readonly checkIn?: (request: CheckInRequest) => Promise<CheckInResult>;
@@ -624,6 +649,7 @@ interface SyncAdapter {
624
649
  readonly rallyId: string;
625
650
  readonly userId: string | null;
626
651
  readonly state: UserRallyState;
652
+ readonly anonymousSessionId?: string;
627
653
  }) => Promise<UserRallyState>;
628
654
  }
629
655
  interface ClientOptions {
@@ -633,6 +659,7 @@ interface ClientOptions {
633
659
  readonly customValidators?: Readonly<Record<string, Validator>>;
634
660
  readonly clock?: () => string;
635
661
  readonly userId?: string | null;
662
+ readonly anonymousSessionId?: string;
636
663
  readonly offlineQueue?: OfflineQueue;
637
664
  }
638
665
  type StorageOrOptions = StampStorage | ClientOptions;
@@ -642,6 +669,7 @@ declare class StampRallyClient {
642
669
  getConfig(): RallyConfig;
643
670
  getState(): UserRallyState | null;
644
671
  getUserId(): string | null;
672
+ getAnonymousSessionId(): string;
645
673
  get syncState(): SyncState;
646
674
  get pendingCount(): number;
647
675
  subscribe(listener: ClientListener): () => void;
@@ -764,4 +792,4 @@ type SnapshotTokenVerification<T extends SnapshotTokenPayload = SnapshotTokenPay
764
792
  declare function createSignedSnapshotToken<T extends SnapshotTokenPayload>(payload: T, secretKey: SnapshotSecretKey): Promise<string>;
765
793
  declare function verifySnapshotToken<T extends SnapshotTokenPayload = SnapshotTokenPayload>(token: string, secretKey: SnapshotSecretKey, now?: number): Promise<SnapshotTokenVerification<T>>;
766
794
 
767
- 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 MergeConflictOptions, type NfcDetectorOptions, type NfcVerificationContext, type OfflineConflict, type OfflineConflictResult, type OfflineOperation, type OfflineOperationError, type OfflineOperationResponse, type OfflineOperationStatus, OfflineQueue, type OfflineQueueOptions, type OfflineQueueStorage, type OfflineResult, type OfflineSender, 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 RallyConfig, type RallySnapshot, type RedemptionMethod, 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 SyncState, THEME_PRESETS, type ThemePreset, type ThemePresetId, type UserRallyState, type ValidationError, type Validator, type VerificationContext, assertPublicConfig, calculateDistanceMeters, calculateProgress, consumeReward, createClaimTicketNumber, createSecureToken, createSignedSnapshotToken, createUniqueClaimTicketNumber, evaluateCondition, evaluateConditionDetailed, evaluateSpotStatus, exportProgressToken, getCurrentGeoContext, getOrderedSpots, getSpotStatus, importProgressToken, isGeolocationSupported, isNfcSupported, isPublicConfig, isQrSupported, isRewardState, isStampRallyState, issueClaimTicketNumber, normalizePasscode, parseAdminConfig, parsePublicConfig, processStamp, readNfcContext, readQrContext, reconcileRewardStates, resolveLocalizedText, resolveRallyStateConflict, safeParseAdminConfig, safeParsePublicConfig, sanitizeAdminConfig, storageKey, toLocalizedString, toPublicConfig, updateLocalizedField, validatePublicConfigSafety, validateRallyConfigRelations, verifyPasscode, verifySecureToken, verifySnapshotToken };
795
+ 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 MergeConflictOptions, type NfcDetectorOptions, type NfcVerificationContext, type OfflineConflict, type OfflineConflictResult, type OfflineOperation, type OfflineOperationError, type OfflineOperationLifecycleStatus, type OfflineOperationResponse, type OfflineOperationStatus, OfflineQueue, type OfflineQueueOptions, type OfflineQueueStorage, type OfflineResult, type OfflineSender, 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 RallyConfig, type RallyInventory, type RallyInventoryState, type RallySnapshot, type RedemptionMethod, 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 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, parseAdminConfig, parsePublicConfig, processStamp, readNfcContext, readQrContext, reconcileRewardStates, resolveLocalizedText, resolveRallyStateConflict, safeParseAdminConfig, safeParsePublicConfig, sanitizeAdminConfig, storageKey, toLocalizedString, toPublicConfig, updateLocalizedField, validatePublicConfigSafety, validateRallyConfigRelations, verifyPasscode, verifySecureToken, verifySnapshotToken };
package/dist/index.js CHANGED
@@ -615,7 +615,13 @@ function cloneState(state) {
615
615
  return {
616
616
  ...state,
617
617
  records: state.records.map(cloneRecord),
618
- ...state.rewards === void 0 ? {} : { rewards: state.rewards.map(cloneRewardState) }
618
+ ...state.rewards === void 0 ? {} : { rewards: state.rewards.map(cloneRewardState) },
619
+ ...state.inventory === void 0 ? {} : {
620
+ inventory: {
621
+ ...state.inventory,
622
+ ...state.inventory.rewardRemaining === void 0 ? {} : { rewardRemaining: { ...state.inventory.rewardRemaining } }
623
+ }
624
+ }
619
625
  };
620
626
  }
621
627
  function isRecord(value) {
@@ -635,7 +641,7 @@ function isRewardState(value) {
635
641
  function isStampRallyState(value) {
636
642
  if (typeof value !== "object" || value === null) return false;
637
643
  const state = value;
638
- return typeof state.rallyId === "string" && (typeof state.userId === "string" || state.userId === null) && typeof state.updatedAt === "string" && Array.isArray(state.records) && state.records.every(isRecord) && (state.rewards === void 0 || Array.isArray(state.rewards) && state.rewards.every(isRewardState));
644
+ return typeof state.rallyId === "string" && (typeof state.userId === "string" || state.userId === null) && typeof state.updatedAt === "string" && Array.isArray(state.records) && state.records.every(isRecord) && (state.rewards === void 0 || Array.isArray(state.rewards) && state.rewards.every(isRewardState)) && (state.inventory === void 0 || typeof state.inventory === "object" && state.inventory !== null && !Array.isArray(state.inventory) && (state.inventory.sharedRemaining === void 0 || typeof state.inventory.sharedRemaining === "number" && Number.isInteger(state.inventory.sharedRemaining) && state.inventory.sharedRemaining >= 0) && (state.inventory.rewardRemaining === void 0 || typeof state.inventory.rewardRemaining === "object" && state.inventory.rewardRemaining !== null && !Array.isArray(state.inventory.rewardRemaining)));
639
645
  }
640
646
  function isValidDate(value) {
641
647
  return typeof value === "string" && !Number.isNaN(Date.parse(value));
@@ -680,6 +686,35 @@ var InMemoryStorage = class {
680
686
  function storageKey(rallyId, userId) {
681
687
  return `stamprally:${rallyId}:${userId ?? "anonymous"}`;
682
688
  }
689
+ function createAnonymousSessionId(storage) {
690
+ const key = "stamprally:anonymous-session-id";
691
+ try {
692
+ const browserStorage = typeof window === "undefined" ? null : window.localStorage;
693
+ const value = storage?.getItem(key) ?? browserStorage?.getItem(key);
694
+ if (value !== null && value !== void 0 && isUuidV4(value)) return value;
695
+ const generated = randomUuidV4();
696
+ (storage ?? browserStorage)?.setItem(key, generated);
697
+ return generated;
698
+ } catch {
699
+ return randomUuidV4();
700
+ }
701
+ }
702
+ function isUuidV4(value) {
703
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);
704
+ }
705
+ function randomUuidV4() {
706
+ const cryptoApi3 = globalThis.crypto;
707
+ if (cryptoApi3?.randomUUID !== void 0) return cryptoApi3.randomUUID();
708
+ if (cryptoApi3?.getRandomValues !== void 0) {
709
+ const bytes2 = cryptoApi3.getRandomValues(new Uint8Array(16));
710
+ bytes2[6] = (bytes2[6] ?? 0) & 15 | 64;
711
+ bytes2[8] = (bytes2[8] ?? 0) & 63 | 128;
712
+ const hex = Array.from(bytes2, (byte) => byte.toString(16).padStart(2, "0")).join("");
713
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
714
+ }
715
+ const random = `${Date.now().toString(16)}${Math.random().toString(16).slice(2)}`.padEnd(32, "0").slice(0, 32);
716
+ return `${random.slice(0, 8)}-${random.slice(8, 12)}-4${random.slice(13, 16)}-8${random.slice(17, 20)}-${random.slice(20)}`;
717
+ }
683
718
  var defaultStorageWarningHandler = (error) => {
684
719
  console.warn(`[@stamprally/core] ${error.message}`, error);
685
720
  };
@@ -1069,6 +1104,7 @@ var StampRallyClient = class {
1069
1104
  #config;
1070
1105
  #offlineQueue;
1071
1106
  #userId;
1107
+ #anonymousSessionId;
1072
1108
  #state = null;
1073
1109
  #initialization = null;
1074
1110
  #queue = Promise.resolve();
@@ -1076,7 +1112,8 @@ var StampRallyClient = class {
1076
1112
  this.#config = config;
1077
1113
  this.#options = isStorage(storageOrOptions) ? { storage: storageOrOptions } : storageOrOptions;
1078
1114
  this.#storage = this.#options.storage ?? new InMemoryStorage();
1079
- this.#userId = this.#options.userId ?? null;
1115
+ this.#anonymousSessionId = this.#options.anonymousSessionId ?? createAnonymousSessionId();
1116
+ this.#userId = this.#options.userId ?? this.#anonymousSessionId;
1080
1117
  this.#offlineQueue = this.#options.offlineQueue;
1081
1118
  this.#offlineQueue?.setSyncResultListener((event) => this.#handleOfflineSyncResult(event));
1082
1119
  }
@@ -1089,6 +1126,9 @@ var StampRallyClient = class {
1089
1126
  getUserId() {
1090
1127
  return this.#userId;
1091
1128
  }
1129
+ getAnonymousSessionId() {
1130
+ return this.#anonymousSessionId;
1131
+ }
1092
1132
  get syncState() {
1093
1133
  return this.#offlineQueue?.syncState ?? "idle";
1094
1134
  }
@@ -1126,11 +1166,12 @@ var StampRallyClient = class {
1126
1166
  }
1127
1167
  switchUser(newUserId) {
1128
1168
  return this.#enqueue(async () => {
1129
- if (this.#userId === newUserId && this.#state !== null) return this.#state;
1130
- this.#userId = newUserId;
1169
+ const nextUserId = newUserId ?? this.#anonymousSessionId;
1170
+ if (this.#userId === nextUserId && this.#state !== null) return this.#state;
1171
+ this.#userId = nextUserId;
1131
1172
  this.#state = null;
1132
1173
  this.#initialization = null;
1133
- await this.#offlineQueue?.switchUser(newUserId);
1174
+ await this.#offlineQueue?.switchUser(nextUserId);
1134
1175
  return this.initialize();
1135
1176
  });
1136
1177
  }
@@ -1198,7 +1239,8 @@ var StampRallyClient = class {
1198
1239
  proofData,
1199
1240
  idempotencyKey: options.idempotencyKey ?? id("check-in"),
1200
1241
  now,
1201
- state: current
1242
+ state: current,
1243
+ ...this.#userId === this.#anonymousSessionId ? { anonymousSessionId: this.#anonymousSessionId } : {}
1202
1244
  };
1203
1245
  const remote = this.#options.syncAdapter?.checkIn;
1204
1246
  if (options.sync !== false && remote !== void 0) {
@@ -1254,7 +1296,8 @@ var StampRallyClient = class {
1254
1296
  idempotencyKey: options.idempotencyKey ?? id("claim"),
1255
1297
  now,
1256
1298
  options,
1257
- state: current
1299
+ state: current,
1300
+ ...this.#userId === this.#anonymousSessionId ? { anonymousSessionId: this.#anonymousSessionId } : {}
1258
1301
  };
1259
1302
  const remote = this.#options.syncAdapter?.claimReward;
1260
1303
  if (options.sync !== false && remote !== void 0) {
@@ -1306,13 +1349,10 @@ var StampRallyClient = class {
1306
1349
  const serverState = await adapter.sync({
1307
1350
  rallyId: this.#config.id,
1308
1351
  userId: this.#userId,
1309
- state: this.#state ?? current
1310
- });
1311
- const localState = this.#state ?? current;
1312
- const merged = this.#offlineQueue === void 0 ? serverState : resolveRallyStateConflict(serverState, localState, {
1313
- policy: this.#offlineQueue.conflictPolicy
1352
+ state: this.#state ?? current,
1353
+ ...this.#userId === this.#anonymousSessionId ? { anonymousSessionId: this.#anonymousSessionId } : {}
1314
1354
  });
1315
- const next = this.#reconcile(merged);
1355
+ const next = this.#reconcile(serverState);
1316
1356
  await this.#storage.save(next);
1317
1357
  this.#state = next;
1318
1358
  this.#emit(next);
@@ -1526,6 +1566,11 @@ function errorValue(value, fallbackCode) {
1526
1566
  }
1527
1567
  var syncLocks = /* @__PURE__ */ new Map();
1528
1568
  var SYNC_LOCK_TTL_MS = 3e4;
1569
+ var DEFAULT_RETRY_OPTIONS = {
1570
+ maxRetries: 0,
1571
+ initialIntervalMs: 250,
1572
+ backoffMultiplier: 2
1573
+ };
1529
1574
  function randomId() {
1530
1575
  return globalThis.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`;
1531
1576
  }
@@ -1544,6 +1589,7 @@ var OfflineQueue = class {
1544
1589
  #syncPromise = null;
1545
1590
  #syncResultListener;
1546
1591
  #synchronizeInstances;
1592
+ #retryOptions;
1547
1593
  #instanceId = randomId();
1548
1594
  #lockStorage;
1549
1595
  #storageListener;
@@ -1559,6 +1605,15 @@ var OfflineQueue = class {
1559
1605
  this.#conflictPolicy = options.conflictPolicy ?? "server_wins";
1560
1606
  this.#onSyncConflict = options.onSyncConflict;
1561
1607
  this.#synchronizeInstances = options.synchronizeInstances ?? true;
1608
+ const retryOptions = {
1609
+ ...DEFAULT_RETRY_OPTIONS,
1610
+ ...options.retryOptions ?? options.syncRetryOptions ?? options.retry ?? {}
1611
+ };
1612
+ this.#retryOptions = {
1613
+ maxRetries: Math.max(0, Math.floor(retryOptions.maxRetries)),
1614
+ initialIntervalMs: Math.max(0, retryOptions.initialIntervalMs),
1615
+ backoffMultiplier: Math.max(1, retryOptions.backoffMultiplier)
1616
+ };
1562
1617
  this.#lockStorage = options.storageLike ?? globalThis.localStorage ?? null;
1563
1618
  if (this.#synchronizeInstances) this.#subscribeToExternalChanges();
1564
1619
  }
@@ -1591,7 +1646,7 @@ var OfflineQueue = class {
1591
1646
  }
1592
1647
  async initialize() {
1593
1648
  if (this.#loaded) return;
1594
- this.#operations = [...await this.#storage.load(this.#storageKey())];
1649
+ this.#operations = (await this.#storage.load(this.#storageKey())).map(normalizeOperation);
1595
1650
  this.#loaded = true;
1596
1651
  }
1597
1652
  /** Releases browser listeners when the queue is no longer used. */
@@ -1636,7 +1691,7 @@ var OfflineQueue = class {
1636
1691
  await this.initialize();
1637
1692
  const id2 = operationId(operation);
1638
1693
  if (this.#operations.some((item) => operationId(item) === id2)) return;
1639
- this.#operations = [...this.#operations, operation];
1694
+ this.#operations = [...this.#operations, { ...operation, status: "PENDING", attempts: 0 }];
1640
1695
  await this.#storage.save(this.#storageKey(), this.#operations);
1641
1696
  this.#announceChange();
1642
1697
  }
@@ -1666,6 +1721,33 @@ var OfflineQueue = class {
1666
1721
  return this.sync(sender);
1667
1722
  }
1668
1723
  async #run(sender) {
1724
+ const locks = globalThis.navigator?.locks;
1725
+ if (locks !== void 0) {
1726
+ let callbackStarted = false;
1727
+ try {
1728
+ const acquired = await locks.request(
1729
+ `stamprally:${this.#storageKey()}:sync`,
1730
+ { ifAvailable: true },
1731
+ async (lock) => {
1732
+ if (lock === null) {
1733
+ await this.#reloadFromStorage();
1734
+ this.#state = "idle";
1735
+ return false;
1736
+ }
1737
+ callbackStarted = true;
1738
+ await this.#runWithStorageLock(sender);
1739
+ return true;
1740
+ }
1741
+ );
1742
+ if (!acquired) return;
1743
+ return;
1744
+ } catch (error) {
1745
+ if (callbackStarted) throw error;
1746
+ }
1747
+ }
1748
+ await this.#runWithStorageLock(sender);
1749
+ }
1750
+ async #runWithStorageLock(sender) {
1669
1751
  this.#state = "syncing";
1670
1752
  this.#error = null;
1671
1753
  if (!this.#acquireSyncLock()) {
@@ -1677,21 +1759,36 @@ var OfflineQueue = class {
1677
1759
  while (this.#operations.length > 0) {
1678
1760
  const operation = this.#operations[0];
1679
1761
  if (operation === void 0) break;
1680
- let rawResult;
1681
- try {
1682
- rawResult = await sender(operation);
1683
- } catch (cause) {
1684
- throw new Error(errorValue(cause, "RETRYABLE_ERROR").message);
1685
- }
1686
- const response = this.#normalizeResponse(rawResult);
1687
- if (response.status === "RETRYABLE_ERROR") {
1762
+ let attempt = 0;
1763
+ let response;
1764
+ while (true) {
1765
+ await this.#updateOperationStatus("IN_FLIGHT", attempt);
1766
+ try {
1767
+ response = this.#normalizeResponse(await sender(operation));
1768
+ } catch (cause) {
1769
+ response = {
1770
+ status: "RETRYABLE_ERROR",
1771
+ error: errorValue(cause, "RETRYABLE_ERROR")
1772
+ };
1773
+ }
1774
+ if (response.status !== "RETRYABLE_ERROR") break;
1688
1775
  const error2 = errorValue(response.error ?? response.reason, "RETRYABLE_ERROR");
1776
+ await this.#updateOperationStatus("PENDING", attempt + 1);
1689
1777
  await this.#syncResultListener?.({ operation, status: response.status, error: error2 });
1690
- throw new Error(error2.message);
1778
+ if (attempt >= this.#retryOptions.maxRetries) throw new Error(error2.message);
1779
+ const interval = this.#retryOptions.initialIntervalMs * this.#retryOptions.backoffMultiplier ** attempt;
1780
+ await new Promise((resolve) => setTimeout(resolve, Math.max(0, interval)));
1781
+ attempt += 1;
1691
1782
  }
1692
1783
  const result = response.result;
1693
1784
  const state = response.state ?? (result !== void 0 && "conflict" in result && result.conflict === true ? await this.resolveConflict(operation, result.localState, result.serverState) : result !== void 0 && "ok" in result && result.ok ? result.value.state : void 0);
1694
1785
  const error = response.status === "REJECTED_PERMANENT" ? errorValue(response.error ?? response.reason, "REJECTED_PERMANENT") : void 0;
1786
+ await this.#updateOperationStatus(
1787
+ response.status === "ACCEPTED" ? "ACCEPTED" : "REJECTED",
1788
+ attempt + 1
1789
+ );
1790
+ const fallbackState = response.status === "REJECTED_PERMANENT" ? operation.request.state : void 0;
1791
+ const eventState = state ?? fallbackState;
1695
1792
  this.#operations = this.#operations.slice(1);
1696
1793
  await this.#storage.save(this.#storageKey(), this.#operations);
1697
1794
  this.#announceChange();
@@ -1700,7 +1797,7 @@ var OfflineQueue = class {
1700
1797
  ...result === void 0 ? {} : { result },
1701
1798
  status: response.status,
1702
1799
  ...error === void 0 ? {} : { error },
1703
- ...state === void 0 ? {} : { state }
1800
+ ...eventState === void 0 ? {} : { state: eventState }
1704
1801
  });
1705
1802
  }
1706
1803
  this.#state = "idle";
@@ -1712,6 +1809,13 @@ var OfflineQueue = class {
1712
1809
  this.#releaseSyncLock();
1713
1810
  }
1714
1811
  }
1812
+ async #updateOperationStatus(status, attempts) {
1813
+ const operation = this.#operations[0];
1814
+ if (operation === void 0) return;
1815
+ this.#operations = [{ ...operation, status, attempts }, ...this.#operations.slice(1)];
1816
+ await this.#storage.save(this.#storageKey(), this.#operations);
1817
+ this.#announceChange();
1818
+ }
1715
1819
  #subscribeToExternalChanges() {
1716
1820
  const windowLike = globalThis.window;
1717
1821
  if (windowLike !== void 0) {
@@ -1739,7 +1843,7 @@ var OfflineQueue = class {
1739
1843
  async #reloadFromStorage() {
1740
1844
  if (this.#state === "syncing") return;
1741
1845
  try {
1742
- this.#operations = [...await this.#storage.load(this.#storageKey())];
1846
+ this.#operations = (await this.#storage.load(this.#storageKey())).map(normalizeOperation);
1743
1847
  this.#loaded = true;
1744
1848
  } catch {
1745
1849
  }
@@ -1809,6 +1913,13 @@ var OfflineQueue = class {
1809
1913
  return resolveRallyStateConflict(serverState, localState, { policy });
1810
1914
  }
1811
1915
  };
1916
+ function normalizeOperation(operation) {
1917
+ return {
1918
+ ...operation,
1919
+ status: operation.status === "IN_FLIGHT" ? "PENDING" : operation.status ?? "PENDING",
1920
+ attempts: operation.attempts ?? 0
1921
+ };
1922
+ }
1812
1923
 
1813
1924
  // src/crypto/token.ts
1814
1925
  var encoder = new TextEncoder();
@@ -2377,6 +2488,8 @@ function condition(value, path, errors, isPublic) {
2377
2488
  finiteNumber(value, "latitude", path, errors);
2378
2489
  finiteNumber(value, "longitude", path, errors);
2379
2490
  finiteNumber(value, "radiusMeters", path, errors, 0);
2491
+ if (typeof value.radiusMeters === "number" && value.radiusMeters <= 0)
2492
+ add(errors, `${path}.radiusMeters`, "Expected a radius greater than 0.", "out_of_range");
2380
2493
  if (typeof value.latitude === "number" && (value.latitude < -90 || value.latitude > 90))
2381
2494
  add(errors, `${path}.latitude`, "Expected a latitude between -90 and 90.", "out_of_range");
2382
2495
  if (typeof value.longitude === "number" && (value.longitude < -180 || value.longitude > 180))
@@ -2787,6 +2900,6 @@ async function verifySnapshotToken(token, secretKey, now = Date.now()) {
2787
2900
  }
2788
2901
  }
2789
2902
 
2790
- export { ConfigValidationError, DEFAULT_SHEET_THEME, MemoryQueueStorage as InMemoryOfflineQueueStorage, InMemoryStorage, IndexedDBAdapter, IndexedDBOfflineQueueStorage, LocalStorageAdapter, OfflineQueue, StampRallyClient, StorageAdapterError, THEME_PRESETS, assertPublicConfig, calculateDistanceMeters, calculateProgress, consumeReward, createClaimTicketNumber, createSecureToken, createSignedSnapshotToken, createUniqueClaimTicketNumber, evaluateCondition, evaluateConditionDetailed, evaluateSpotStatus, exportProgressToken, getCurrentGeoContext, getOrderedSpots, getSpotStatus, importProgressToken, isGeolocationSupported, isNfcSupported, isPublicConfig, isQrSupported, isRewardState, isStampRallyState, issueClaimTicketNumber, normalizePasscode, parseAdminConfig, parsePublicConfig, processStamp, readNfcContext, readQrContext, reconcileRewardStates, resolveLocalizedText, resolveRallyStateConflict, safeParseAdminConfig, safeParsePublicConfig, sanitizeAdminConfig, storageKey, toLocalizedString, toPublicConfig, updateLocalizedField, validatePublicConfigSafety, validateRallyConfigRelations, verifyPasscode, verifySecureToken, verifySnapshotToken };
2903
+ export { ConfigValidationError, DEFAULT_SHEET_THEME, MemoryQueueStorage as InMemoryOfflineQueueStorage, InMemoryStorage, IndexedDBAdapter, IndexedDBOfflineQueueStorage, LocalStorageAdapter, OfflineQueue, StampRallyClient, StorageAdapterError, THEME_PRESETS, 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, parseAdminConfig, parsePublicConfig, processStamp, readNfcContext, readQrContext, reconcileRewardStates, resolveLocalizedText, resolveRallyStateConflict, safeParseAdminConfig, safeParsePublicConfig, sanitizeAdminConfig, storageKey, toLocalizedString, toPublicConfig, updateLocalizedField, validatePublicConfigSafety, validateRallyConfigRelations, verifyPasscode, verifySecureToken, verifySnapshotToken };
2791
2904
  //# sourceMappingURL=index.js.map
2792
2905
  //# sourceMappingURL=index.js.map