@stamprally/server 0.15.0 → 0.16.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
@@ -18,6 +18,10 @@ interface ClaimRewardTransactionParams {
18
18
  readonly idempotencyKey?: string;
19
19
  readonly proofData?: unknown;
20
20
  readonly idempotencyTtlMs?: number;
21
+ /** The configured per-reward stock limit, or null for unlimited stock. */
22
+ readonly rewardStockLimit: number | null;
23
+ /** The configured shared stock limit, or null when shared inventory is disabled. */
24
+ readonly sharedStockLimit: number | null;
21
25
  /** Used when the first claim is made before a user state has been stored. */
22
26
  readonly initialUserState?: UserRallyState;
23
27
  readonly stockKey?: string;
@@ -72,6 +76,8 @@ interface ServerPersistenceAdapter {
72
76
  readonly success: boolean;
73
77
  readonly error?: string;
74
78
  }>;
79
+ /** Set false when the adapter cannot persist per-reward inventory atomically. */
80
+ readonly supportsRewardStock?: boolean;
75
81
  acquireLock(rallyId: string, lockKey: string, ttlMs: number): Promise<boolean>;
76
82
  releaseLock(rallyId: string, lockKey: string): Promise<void>;
77
83
  getRewardStock(rallyId: string, rewardId: string): Promise<number | null>;
@@ -95,6 +101,7 @@ interface InMemoryServerPersistenceOptions {
95
101
  }
96
102
  declare class InMemoryServerPersistenceAdapter implements ServerPersistenceAdapter {
97
103
  #private;
104
+ readonly supportsRewardStock = true;
98
105
  constructor(options?: InMemoryServerPersistenceOptions);
99
106
  acquireLock(rallyId: string, key: string, ttlMs: number): Promise<boolean>;
100
107
  releaseLock(rallyId: string, key: string): Promise<void>;
@@ -135,7 +142,7 @@ declare class InMemoryServerPersistenceAdapter implements ServerPersistenceAdapt
135
142
  /** @deprecated Use recordUserClaim with a ticket number and timestamp. */
136
143
  recordClaim(params: UserClaimRecord): Promise<void>;
137
144
  recordClaim(rallyId: string, userId: string, rewardId: string): Promise<void>;
138
- runTransaction<T>(_rallyId: string, operation: (transaction: ServerPersistenceAdapter) => Promise<T>): Promise<T>;
145
+ runTransaction<T>(rallyId: string, operation: (transaction: ServerPersistenceAdapter) => Promise<T>): Promise<T>;
139
146
  }
140
147
 
141
148
  /**
@@ -211,11 +218,27 @@ type RequestValidationResult<T> = {
211
218
  readonly success: false;
212
219
  readonly errors: ReadonlyArray<RequestValidationError>;
213
220
  };
221
+ declare class RequestValidationException extends Error {
222
+ readonly code = "VALIDATION_FAILED";
223
+ readonly errors: ReadonlyArray<RequestValidationError>;
224
+ constructor(errors: ReadonlyArray<RequestValidationError>);
225
+ }
214
226
  declare function validateCheckInRequest(value: unknown): RequestValidationResult<CheckInRequest>;
215
227
  declare function validateClaimRewardRequest(value: unknown): RequestValidationResult<ClaimRewardRequest>;
228
+ declare function assertValidCheckInParams(value: unknown, config: AdminRallyConfig): asserts value is CheckInRequest & {
229
+ readonly userId: string;
230
+ };
231
+ declare function assertValidClaimParams(value: unknown, config: AdminRallyConfig): asserts value is ClaimRewardRequest & {
232
+ readonly userId: string;
233
+ };
234
+ declare function assertValidSyncParams(value: unknown, config: AdminRallyConfig): asserts value is {
235
+ readonly rallyId: string;
236
+ readonly userId: string;
237
+ };
216
238
  declare function validateSyncRequest(value: unknown): RequestValidationResult<{
217
239
  readonly rallyId: string;
218
240
  readonly userId?: string;
241
+ readonly anonymousSessionId?: string;
219
242
  }>;
220
243
 
221
244
  type ErrorResponse = {
@@ -240,15 +263,22 @@ declare class StampRallyServer {
240
263
  handleCheckIn(request: Request): Promise<Response>;
241
264
  handleClaimReward(request: Request): Promise<Response>;
242
265
  handleSync(request: Request): Promise<Response>;
243
- checkIn(request: CheckInRequest & {
244
- readonly userId: string;
245
- }): Promise<CheckInResponse>;
246
- claimReward(request: ClaimRewardRequest & {
247
- readonly userId: string;
248
- }): Promise<ClaimResponse>;
266
+ checkIn(request: CheckInRequest): Promise<CheckInResponse>;
267
+ claimReward(request: ClaimRewardRequest): Promise<ClaimResponse>;
249
268
  sync(rallyId: string, userId: string): Promise<UserRallyState>;
269
+ syncProgress(request: {
270
+ readonly rallyId: string;
271
+ readonly userId?: string;
272
+ readonly anonymousSessionId?: string;
273
+ }): Promise<UserRallyState>;
250
274
  }
251
275
 
276
+ /**
277
+ * Runs the minimum atomicity and idempotency contract against a persistence adapter.
278
+ * The function throws a descriptive error when the adapter violates the contract.
279
+ */
280
+ declare function runPersistenceAdapterComplianceTests(createAdapter: () => Promise<ServerPersistenceAdapter>): Promise<void>;
281
+
252
282
  interface AuditLog {
253
283
  readonly id: string;
254
284
  readonly timestamp: string;
@@ -264,6 +294,7 @@ type SyncOperationStatus = "ACCEPTED" | "REJECTED_PERMANENT" | "RETRYABLE_ERROR"
264
294
  interface CheckInRequest {
265
295
  readonly rallyId: string;
266
296
  readonly userId?: string;
297
+ readonly anonymousSessionId?: string;
267
298
  readonly spotId: string;
268
299
  readonly context: _stamprally_core.VerificationContext;
269
300
  readonly idempotencyKey: string;
@@ -272,6 +303,7 @@ interface CheckInRequest {
272
303
  interface ClaimRewardRequest {
273
304
  readonly rallyId: string;
274
305
  readonly userId?: string;
306
+ readonly anonymousSessionId?: string;
275
307
  readonly rewardId: string;
276
308
  readonly idempotencyKey: string;
277
309
  readonly staffPasscode?: string;
@@ -294,10 +326,10 @@ interface ServerOptions {
294
326
  readonly authenticate?: (request: Request) => Promise<string | AuthenticationContext | null> | string | AuthenticationContext | null;
295
327
  readonly customValidators?: Readonly<Record<string, _stamprally_core.Validator>>;
296
328
  readonly now?: () => string;
297
- readonly anonymousPolicy?: "session_scoped" | "reject";
329
+ readonly anonymousPolicy?: "session_scoped" | "reject" | "shared_global_opt_in_insecure";
298
330
  }
299
331
  interface AuthenticationContext {
300
332
  readonly authenticatedUserId: string;
301
333
  }
302
334
 
303
- export { type AuditLog, type AuthenticationContext, type CheckInRequest, type CheckInResponse, type CheckInTransactionMutation, type CheckInTransactionParams, type ClaimRewardRequest, type ClaimRewardTransactionMutation, type ClaimRewardTransactionParams, InMemoryServerPersistenceAdapter, type InMemoryServerPersistenceOptions, type RedisMultiExecutor, type RequestValidationError, type RequestValidationResult, type ServerOptions, type ServerPersistenceAdapter, type SqlCheckInStore, type SqlClaimRewardStore, type SqlTransactionDatabase, StampRallyServer, type SyncOperationStatus, type UserClaimRecord, executeCheckInTransaction, executeClaimRewardTransaction, executeRedisTransaction, validateCheckInRequest, validateClaimRewardRequest, validateSyncRequest };
335
+ export { type AuditLog, type AuthenticationContext, type CheckInRequest, type CheckInResponse, type CheckInTransactionMutation, type CheckInTransactionParams, type ClaimRewardRequest, type ClaimRewardTransactionMutation, type ClaimRewardTransactionParams, InMemoryServerPersistenceAdapter, type InMemoryServerPersistenceOptions, type RedisMultiExecutor, type RequestValidationError, RequestValidationException, type RequestValidationResult, type ServerOptions, type ServerPersistenceAdapter, type SqlCheckInStore, type SqlClaimRewardStore, type SqlTransactionDatabase, StampRallyServer, type SyncOperationStatus, type UserClaimRecord, assertValidCheckInParams, assertValidClaimParams, assertValidSyncParams, executeCheckInTransaction, executeClaimRewardTransaction, executeRedisTransaction, runPersistenceAdapterComplianceTests, validateCheckInRequest, validateClaimRewardRequest, validateSyncRequest };
package/dist/index.d.ts CHANGED
@@ -18,6 +18,10 @@ interface ClaimRewardTransactionParams {
18
18
  readonly idempotencyKey?: string;
19
19
  readonly proofData?: unknown;
20
20
  readonly idempotencyTtlMs?: number;
21
+ /** The configured per-reward stock limit, or null for unlimited stock. */
22
+ readonly rewardStockLimit: number | null;
23
+ /** The configured shared stock limit, or null when shared inventory is disabled. */
24
+ readonly sharedStockLimit: number | null;
21
25
  /** Used when the first claim is made before a user state has been stored. */
22
26
  readonly initialUserState?: UserRallyState;
23
27
  readonly stockKey?: string;
@@ -72,6 +76,8 @@ interface ServerPersistenceAdapter {
72
76
  readonly success: boolean;
73
77
  readonly error?: string;
74
78
  }>;
79
+ /** Set false when the adapter cannot persist per-reward inventory atomically. */
80
+ readonly supportsRewardStock?: boolean;
75
81
  acquireLock(rallyId: string, lockKey: string, ttlMs: number): Promise<boolean>;
76
82
  releaseLock(rallyId: string, lockKey: string): Promise<void>;
77
83
  getRewardStock(rallyId: string, rewardId: string): Promise<number | null>;
@@ -95,6 +101,7 @@ interface InMemoryServerPersistenceOptions {
95
101
  }
96
102
  declare class InMemoryServerPersistenceAdapter implements ServerPersistenceAdapter {
97
103
  #private;
104
+ readonly supportsRewardStock = true;
98
105
  constructor(options?: InMemoryServerPersistenceOptions);
99
106
  acquireLock(rallyId: string, key: string, ttlMs: number): Promise<boolean>;
100
107
  releaseLock(rallyId: string, key: string): Promise<void>;
@@ -135,7 +142,7 @@ declare class InMemoryServerPersistenceAdapter implements ServerPersistenceAdapt
135
142
  /** @deprecated Use recordUserClaim with a ticket number and timestamp. */
136
143
  recordClaim(params: UserClaimRecord): Promise<void>;
137
144
  recordClaim(rallyId: string, userId: string, rewardId: string): Promise<void>;
138
- runTransaction<T>(_rallyId: string, operation: (transaction: ServerPersistenceAdapter) => Promise<T>): Promise<T>;
145
+ runTransaction<T>(rallyId: string, operation: (transaction: ServerPersistenceAdapter) => Promise<T>): Promise<T>;
139
146
  }
140
147
 
141
148
  /**
@@ -211,11 +218,27 @@ type RequestValidationResult<T> = {
211
218
  readonly success: false;
212
219
  readonly errors: ReadonlyArray<RequestValidationError>;
213
220
  };
221
+ declare class RequestValidationException extends Error {
222
+ readonly code = "VALIDATION_FAILED";
223
+ readonly errors: ReadonlyArray<RequestValidationError>;
224
+ constructor(errors: ReadonlyArray<RequestValidationError>);
225
+ }
214
226
  declare function validateCheckInRequest(value: unknown): RequestValidationResult<CheckInRequest>;
215
227
  declare function validateClaimRewardRequest(value: unknown): RequestValidationResult<ClaimRewardRequest>;
228
+ declare function assertValidCheckInParams(value: unknown, config: AdminRallyConfig): asserts value is CheckInRequest & {
229
+ readonly userId: string;
230
+ };
231
+ declare function assertValidClaimParams(value: unknown, config: AdminRallyConfig): asserts value is ClaimRewardRequest & {
232
+ readonly userId: string;
233
+ };
234
+ declare function assertValidSyncParams(value: unknown, config: AdminRallyConfig): asserts value is {
235
+ readonly rallyId: string;
236
+ readonly userId: string;
237
+ };
216
238
  declare function validateSyncRequest(value: unknown): RequestValidationResult<{
217
239
  readonly rallyId: string;
218
240
  readonly userId?: string;
241
+ readonly anonymousSessionId?: string;
219
242
  }>;
220
243
 
221
244
  type ErrorResponse = {
@@ -240,15 +263,22 @@ declare class StampRallyServer {
240
263
  handleCheckIn(request: Request): Promise<Response>;
241
264
  handleClaimReward(request: Request): Promise<Response>;
242
265
  handleSync(request: Request): Promise<Response>;
243
- checkIn(request: CheckInRequest & {
244
- readonly userId: string;
245
- }): Promise<CheckInResponse>;
246
- claimReward(request: ClaimRewardRequest & {
247
- readonly userId: string;
248
- }): Promise<ClaimResponse>;
266
+ checkIn(request: CheckInRequest): Promise<CheckInResponse>;
267
+ claimReward(request: ClaimRewardRequest): Promise<ClaimResponse>;
249
268
  sync(rallyId: string, userId: string): Promise<UserRallyState>;
269
+ syncProgress(request: {
270
+ readonly rallyId: string;
271
+ readonly userId?: string;
272
+ readonly anonymousSessionId?: string;
273
+ }): Promise<UserRallyState>;
250
274
  }
251
275
 
276
+ /**
277
+ * Runs the minimum atomicity and idempotency contract against a persistence adapter.
278
+ * The function throws a descriptive error when the adapter violates the contract.
279
+ */
280
+ declare function runPersistenceAdapterComplianceTests(createAdapter: () => Promise<ServerPersistenceAdapter>): Promise<void>;
281
+
252
282
  interface AuditLog {
253
283
  readonly id: string;
254
284
  readonly timestamp: string;
@@ -264,6 +294,7 @@ type SyncOperationStatus = "ACCEPTED" | "REJECTED_PERMANENT" | "RETRYABLE_ERROR"
264
294
  interface CheckInRequest {
265
295
  readonly rallyId: string;
266
296
  readonly userId?: string;
297
+ readonly anonymousSessionId?: string;
267
298
  readonly spotId: string;
268
299
  readonly context: _stamprally_core.VerificationContext;
269
300
  readonly idempotencyKey: string;
@@ -272,6 +303,7 @@ interface CheckInRequest {
272
303
  interface ClaimRewardRequest {
273
304
  readonly rallyId: string;
274
305
  readonly userId?: string;
306
+ readonly anonymousSessionId?: string;
275
307
  readonly rewardId: string;
276
308
  readonly idempotencyKey: string;
277
309
  readonly staffPasscode?: string;
@@ -294,10 +326,10 @@ interface ServerOptions {
294
326
  readonly authenticate?: (request: Request) => Promise<string | AuthenticationContext | null> | string | AuthenticationContext | null;
295
327
  readonly customValidators?: Readonly<Record<string, _stamprally_core.Validator>>;
296
328
  readonly now?: () => string;
297
- readonly anonymousPolicy?: "session_scoped" | "reject";
329
+ readonly anonymousPolicy?: "session_scoped" | "reject" | "shared_global_opt_in_insecure";
298
330
  }
299
331
  interface AuthenticationContext {
300
332
  readonly authenticatedUserId: string;
301
333
  }
302
334
 
303
- export { type AuditLog, type AuthenticationContext, type CheckInRequest, type CheckInResponse, type CheckInTransactionMutation, type CheckInTransactionParams, type ClaimRewardRequest, type ClaimRewardTransactionMutation, type ClaimRewardTransactionParams, InMemoryServerPersistenceAdapter, type InMemoryServerPersistenceOptions, type RedisMultiExecutor, type RequestValidationError, type RequestValidationResult, type ServerOptions, type ServerPersistenceAdapter, type SqlCheckInStore, type SqlClaimRewardStore, type SqlTransactionDatabase, StampRallyServer, type SyncOperationStatus, type UserClaimRecord, executeCheckInTransaction, executeClaimRewardTransaction, executeRedisTransaction, validateCheckInRequest, validateClaimRewardRequest, validateSyncRequest };
335
+ export { type AuditLog, type AuthenticationContext, type CheckInRequest, type CheckInResponse, type CheckInTransactionMutation, type CheckInTransactionParams, type ClaimRewardRequest, type ClaimRewardTransactionMutation, type ClaimRewardTransactionParams, InMemoryServerPersistenceAdapter, type InMemoryServerPersistenceOptions, type RedisMultiExecutor, type RequestValidationError, RequestValidationException, type RequestValidationResult, type ServerOptions, type ServerPersistenceAdapter, type SqlCheckInStore, type SqlClaimRewardStore, type SqlTransactionDatabase, StampRallyServer, type SyncOperationStatus, type UserClaimRecord, assertValidCheckInParams, assertValidClaimParams, assertValidSyncParams, executeCheckInTransaction, executeClaimRewardTransaction, executeRedisTransaction, runPersistenceAdapterComplianceTests, validateCheckInRequest, validateClaimRewardRequest, validateSyncRequest };