crossmate

A collaborative crossword app for iOS
Log | Files | Refs | LICENSE

helpers.mjs (1378B)


      1 // Map-backed stand-in for a Durable Object's transactional storage, covering
      2 // only the surface the rate limiters touch (get/put/delete/list + alarms).
      3 // Tests import the worker modules directly and construct the classes against
      4 // this stub, so they exercise the pure logic — not the workers runtime.
      5 export class StubStorage {
      6   constructor() {
      7     this.map = new Map();
      8     this.alarmAt = null;
      9   }
     10 
     11   async get(key) {
     12     return this.map.get(key);
     13   }
     14 
     15   async put(key, value) {
     16     this.map.set(key, value);
     17   }
     18 
     19   async delete(key) {
     20     this.map.delete(key);
     21   }
     22 
     23   async list({ prefix }) {
     24     return new Map([...this.map].filter(([key]) => key.startsWith(prefix)));
     25   }
     26 
     27   async getAlarm() {
     28     return this.alarmAt;
     29   }
     30 
     31   async setAlarm(at) {
     32     this.alarmAt = at;
     33   }
     34 
     35   keys(prefix = "") {
     36     return [...this.map.keys()].filter((key) => key.startsWith(prefix));
     37   }
     38 
     39   // Rewinds every timestamp in a stored rate entry by `millis`, simulating
     40   // the passage of time without the test having to wait for it. Handles both
     41   // rate-value shapes: plain timestamp arrays (push worker) and
     42   // `{room, at}` entry arrays (room worker).
     43   age(key, millis) {
     44     const stored = this.map.get(key);
     45     this.map.set(
     46       key,
     47       stored.map((entry) =>
     48         typeof entry === "number" ? entry - millis : { ...entry, at: entry.at - millis }
     49       )
     50     );
     51   }
     52 }