All files / backend/src/services/workspace file-cache-token.ts

90.47% Statements 19/21
66.66% Branches 4/6
85.71% Functions 6/7
95% Lines 19/20

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69                                      13x 13x 13x             23x 10x     13x 13x   13x 13x 13x 13x 13x         23x 13x 13x 13x 13x                 5x 5x                    
/**
 * File Cache Token
 *
 * Creates a cache token based on file modification times.
 * Used to invalidate configuration caches when files change.
 */
 
import fs from 'fs';
 
/**
 * FileCacheToken generates a unique token based on file modification times
 * Used for cache invalidation when source files change
 */
export class FileCacheToken {
  private files: string[] | null;
  private token: string | null;
  private isBuilt: boolean;
 
  constructor(files: string[]) {
    this.files = files;
    this.token = null;
    this.isBuilt = false;
  }
 
  /**
   * Build the cache token from file modification times
   */
  async build(): Promise<FileCacheToken> {
    if (this.isBuilt) {
      return this;
    }
 
    const signatures: string[] = [];
    const promises = (this.files || []).map(
      (file) =>
        new Promise<void>((resolve, reject) => {
          fs.stat(file, (err, stats) => {
            Iif (err) return reject(err);
            signatures.push(`${file}>${stats.mtime.getTime()}`);
            resolve();
          });
        })
    );
 
    await Promise.all(promises);
    this.token = signatures.sort().join('|');
    this.isBuilt = true;
    this.files = null;
    return this;
  }
 
  /**
   * Check if this token matches another token
   * @param other - Another FileCacheToken to compare against
   * @returns true if tokens match, false otherwise
   */
  async match(other: FileCacheToken): Promise<boolean> {
    await Promise.all([this.build(), other.build()]);
    return this.token === other.token;
  }
 
  /**
   * Get the token value (after building)
   */
  getToken(): string | null {
    return this.token;
  }
}