CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-fluidframework--driver-utils

Collection of utility functions for Fluid drivers

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

url-compression.mddocs/

URL Resolution and Compression

Development utilities for URL resolution and optional compression support for storage operations. Includes compression configuration and factory adapters.

Capabilities

URL Resolution (Development/Testing Only)

⚠️ WARNING: InsecureUrlResolver is intended for development and testing scenarios only. Do not use in production environments.

/**
 * Simple URL resolver for development and testing scenarios
 * WARNING: Not for production use - provides minimal security
 */
class InsecureUrlResolver implements IUrlResolver {
  /**
   * @param hostUrl - Base host URL for the service
   * @param ordererUrl - URL for the ordering service
   * @param storageUrl - URL for the storage service
   * @param deltaStreamUrl - URL for delta stream connections
   * @param tenantId - Tenant identifier
   * @param bearer - Authentication bearer token
   * @param isForNodeTest - Whether this is for Node.js testing (optional)
   */
  constructor(
    hostUrl: string,
    ordererUrl: string,
    storageUrl: string,
    deltaStreamUrl: string,
    tenantId: string,
    bearer: string,
    isForNodeTest?: boolean
  );

  /**
   * Resolve a request to a resolved URL
   * @param request - Request to resolve
   * @returns Promise resolving to resolved URL structure
   */
  resolve(request: IRequest): Promise<IResolvedUrl>;

  /**
   * Get absolute URL from resolved URL and relative path
   * @param resolvedUrl - Previously resolved URL
   * @param relativeUrl - Relative URL to append
   * @returns Promise resolving to absolute URL string
   */
  getAbsoluteUrl(resolvedUrl: IResolvedUrl, relativeUrl: string): Promise<string>;

  /**
   * Create request for creating a new document
   * @param fileName - Optional file name for the new document
   * @returns Request object for document creation
   */
  createCreateNewRequest(fileName?: string): IRequest;
}

Usage Example (Development Only):

import { InsecureUrlResolver } from "@fluidframework/driver-utils";

// ⚠️ DEVELOPMENT/TESTING ONLY
const resolver = new InsecureUrlResolver(
  "http://localhost:7070",  // host
  "http://localhost:7070",  // orderer  
  "http://localhost:7070",  // storage
  "ws://localhost:7070",    // delta stream
  "test-tenant",            // tenant ID
  "test-token",             // bearer token
  true                      // for Node.js testing
);

// Resolve a document URL
const resolvedUrl = await resolver.resolve({
  url: "fluid://localhost/test-container",
  headers: {}
});

// Create new document request
const createRequest = resolver.createCreateNewRequest("my-document");
const newDocUrl = await resolver.resolve(createRequest);

Compression Support

Configuration and utilities for enabling compression in storage operations.

/**
 * Available compression algorithms
 */
enum SummaryCompressionAlgorithm {
  None = 0,
  LZ4 = 1
}

/**
 * Configuration for storage compression
 */
interface ICompressionStorageConfig {
  /** Compression algorithm to use */
  algorithm: SummaryCompressionAlgorithm;
  /** Minimum size in bytes before compression is applied */
  minSizeToCompress: number;
}

/**
 * Default compression configuration with LZ4 algorithm
 */
const DefaultCompressionStorageConfig: ICompressionStorageConfig;

/**
 * Blob name for compression metadata headers
 */
const blobHeadersBlobName: string;

/**
 * Applies compression to document service factory based on configuration
 * @param documentServiceFactory - Factory to wrap with compression
 * @param config - Compression configuration or boolean (true = default config)
 * @returns Wrapped factory with compression support
 */
function applyStorageCompression(
  documentServiceFactory: IDocumentServiceFactory, 
  config?: ICompressionStorageConfig | boolean
): IDocumentServiceFactory;

Usage Examples:

import { 
  applyStorageCompression,
  SummaryCompressionAlgorithm,
  ICompressionStorageConfig,
  blobHeadersBlobName
} from "@fluidframework/driver-utils";

// Apply default compression
const compressedFactory = applyStorageCompression(
  originalFactory, 
  true  // Use default settings
);

// Apply custom compression configuration
const customConfig: ICompressionStorageConfig = {
  algorithm: SummaryCompressionAlgorithm.LZ4,
  minSizeToCompress: 1024  // Only compress files > 1KB
};

const customCompressedFactory = applyStorageCompression(
  originalFactory,
  customConfig
);

// Disable compression
const uncompressedFactory = applyStorageCompression(
  originalFactory,
  false
);

// Check for compression headers blob
if (snapshotTree.blobs[blobHeadersBlobName]) {
  console.log("Snapshot contains compression metadata");
}

Advanced Usage Patterns

Development Environment Setup

import { InsecureUrlResolver } from "@fluidframework/driver-utils";

class DevEnvironmentSetup {
  static createDevResolver(
    port: number = 7070,
    tenantId: string = "dev-tenant"
  ): InsecureUrlResolver {
    const baseUrl = `http://localhost:${port}`;
    const wsUrl = `ws://localhost:${port}`;
    
    return new InsecureUrlResolver(
      baseUrl,      // host
      baseUrl,      // orderer
      baseUrl,      // storage  
      wsUrl,        // delta stream
      tenantId,     // tenant
      "dev-token",  // bearer token
      process.env.NODE_ENV === 'test'
    );
  }
  
  static async createDevDocument(
    resolver: InsecureUrlResolver,
    containerName: string
  ): Promise<IResolvedUrl> {
    const createRequest = resolver.createCreateNewRequest(containerName);
    return await resolver.resolve(createRequest);
  }
  
  static async resolveDevDocument(
    resolver: InsecureUrlResolver,
    documentId: string
  ): Promise<IResolvedUrl> {
    return await resolver.resolve({
      url: `fluid://localhost/${documentId}`,
      headers: {}
    });
  }
}

// Usage in development
const devResolver = DevEnvironmentSetup.createDevResolver(7070);
const newDoc = await DevEnvironmentSetup.createDevDocument(devResolver, "test-doc");
const existingDoc = await DevEnvironmentSetup.resolveDevDocument(devResolver, "existing-doc-id");

Compression Strategy Manager

import { 
  applyStorageCompression,
  SummaryCompressionAlgorithm,
  ICompressionStorageConfig
} from "@fluidframework/driver-utils";

class CompressionStrategyManager {
  static readonly STRATEGIES = {
    // No compression - fastest but largest
    none: {
      algorithm: SummaryCompressionAlgorithm.None,
      minSizeToCompress: Number.MAX_SAFE_INTEGER
    },
    
    // Light compression - good for text-heavy documents
    light: {
      algorithm: SummaryCompressionAlgorithm.LZ4,
      minSizeToCompress: 512  // 512 bytes
    },
    
    // Standard compression - balanced performance/size
    standard: {
      algorithm: SummaryCompressionAlgorithm.LZ4,
      minSizeToCompress: 1024  // 1KB
    },
    
    // Aggressive compression - best size but slower
    aggressive: {
      algorithm: SummaryCompressionAlgorithm.LZ4,
      minSizeToCompress: 256  // 256 bytes
    }
  } as const;
  
  static applyStrategy(
    factory: IDocumentServiceFactory,
    strategyName: keyof typeof CompressionStrategyManager.STRATEGIES
  ): IDocumentServiceFactory {
    const config = this.STRATEGIES[strategyName];
    return applyStorageCompression(factory, config);
  }
  
  static createAdaptiveFactory(
    factory: IDocumentServiceFactory,
    networkSpeed: 'fast' | 'medium' | 'slow' = 'medium'
  ): IDocumentServiceFactory {
    const strategyMap = {
      fast: 'light',      // Prioritize speed
      medium: 'standard', // Balanced
      slow: 'aggressive'  // Prioritize bandwidth savings
    } as const;
    
    return this.applyStrategy(factory, strategyMap[networkSpeed]);
  }
  
  static measureCompressionEffectiveness(
    originalSize: number,
    compressedSize: number
  ): CompressionMetrics {
    const compressionRatio = originalSize / compressedSize;
    const spaceSavings = ((originalSize - compressedSize) / originalSize) * 100;
    
    return {
      originalSize,
      compressedSize,
      compressionRatio,
      spaceSavingsPercent: spaceSavings,
      worthwhileCompression: spaceSavings > 20  // >20% savings
    };
  }
}

interface CompressionMetrics {
  originalSize: number;
  compressedSize: number;
  compressionRatio: number;
  spaceSavingsPercent: number;
  worthwhileCompression: boolean;
}

// Usage
const factory = CompressionStrategyManager.applyStrategy(
  baseFactory, 
  'standard'
);

const adaptiveFactory = CompressionStrategyManager.createAdaptiveFactory(
  baseFactory,
  'slow'  // Optimize for slow networks
);

const metrics = CompressionStrategyManager.measureCompressionEffectiveness(
  10240,  // 10KB original
  3072    // 3KB compressed
);
console.log(`Compression saved ${metrics.spaceSavingsPercent.toFixed(1)}%`);

Multi-Environment URL Resolver

import { InsecureUrlResolver } from "@fluidframework/driver-utils";

class MultiEnvironmentUrlResolver {
  private resolvers = new Map<string, InsecureUrlResolver>();
  private currentEnvironment: string = 'development';
  
  constructor() {
    this.setupEnvironments();
  }
  
  private setupEnvironments(): void {
    // Development environment
    this.resolvers.set('development', new InsecureUrlResolver(
      'http://localhost:7070',
      'http://localhost:7070', 
      'http://localhost:7070',
      'ws://localhost:7070',
      'dev-tenant',
      'dev-token',
      false
    ));
    
    // Testing environment
    this.resolvers.set('testing', new InsecureUrlResolver(
      'http://localhost:8080',
      'http://localhost:8080',
      'http://localhost:8080', 
      'ws://localhost:8080',
      'test-tenant',
      'test-token',
      true
    ));
    
    // Local integration environment
    this.resolvers.set('integration', new InsecureUrlResolver(
      'http://integration.local:9090',
      'http://integration.local:9090',
      'http://integration.local:9090',
      'ws://integration.local:9090',
      'integration-tenant',
      'integration-token',
      false
    ));
  }
  
  setEnvironment(env: string): void {
    if (!this.resolvers.has(env)) {
      throw new Error(`Unknown environment: ${env}`);
    }
    this.currentEnvironment = env;
  }
  
  getCurrentResolver(): InsecureUrlResolver {
    const resolver = this.resolvers.get(this.currentEnvironment);
    if (!resolver) {
      throw new Error(`No resolver configured for environment: ${this.currentEnvironment}`);
    }
    return resolver;
  }
  
  async resolve(request: IRequest): Promise<IResolvedUrl> {
    const resolver = this.getCurrentResolver();
    return await resolver.resolve(request);
  }
  
  async createNewDocument(fileName?: string): Promise<IResolvedUrl> {
    const resolver = this.getCurrentResolver();
    const createRequest = resolver.createCreateNewRequest(fileName);
    return await resolver.resolve(createRequest);
  }
  
  addCustomEnvironment(
    name: string, 
    hostUrl: string,
    tenantId: string,
    bearerToken: string
  ): void {
    const resolver = new InsecureUrlResolver(
      hostUrl, hostUrl, hostUrl, 
      hostUrl.replace('http', 'ws'),
      tenantId, bearerToken, false
    );
    
    this.resolvers.set(name, resolver);
  }
  
  get availableEnvironments(): string[] {
    return Array.from(this.resolvers.keys());
  }
  
  get currentEnvironmentName(): string {
    return this.currentEnvironment;
  }
}

// Usage
const multiResolver = new MultiEnvironmentUrlResolver();

// Switch environments
multiResolver.setEnvironment('testing');
const testDoc = await multiResolver.createNewDocument('test-document');

multiResolver.setEnvironment('development');  
const devDoc = await multiResolver.resolve({
  url: 'fluid://localhost/my-document',
  headers: {}
});

// Add custom environment
multiResolver.addCustomEnvironment(
  'staging',
  'https://staging.example.com',
  'staging-tenant',
  'staging-auth-token'
);

multiResolver.setEnvironment('staging');
console.log(`Available environments: ${multiResolver.availableEnvironments.join(', ')}`);

Compression Performance Monitor

import { applyStorageCompression } from "@fluidframework/driver-utils";

class CompressionPerformanceMonitor {
  private metrics = new Map<string, CompressionMetric[]>();
  
  wrapFactoryWithMonitoring(
    factory: IDocumentServiceFactory,
    config: ICompressionStorageConfig,
    label: string = 'default'
  ): IDocumentServiceFactory {
    const compressedFactory = applyStorageCompression(factory, config);
    
    // Wrap with monitoring (simplified implementation)
    return {
      ...compressedFactory,
      createDocumentService: async (...args) => {
        const service = await compressedFactory.createDocumentService(...args);
        return this.wrapServiceWithMonitoring(service, label);
      }
    };
  }
  
  private wrapServiceWithMonitoring(
    service: IDocumentService,
    label: string
  ): IDocumentService {
    return {
      ...service,
      connectToStorage: async () => {
        const storage = await service.connectToStorage();
        return this.wrapStorageWithMonitoring(storage, label);
      }
    };
  }
  
  private wrapStorageWithMonitoring(
    storage: IDocumentStorageService,
    label: string
  ): IDocumentStorageService {
    return {
      ...storage,
      createBlob: async (file: ArrayBufferLike) => {
        const start = performance.now();
        const originalSize = file.byteLength;
        
        const result = await storage.createBlob(file);
        
        const duration = performance.now() - start;
        this.recordMetric(label, {
          operation: 'createBlob',
          originalSize,
          compressedSize: file.byteLength, // Simplified
          duration,
          timestamp: Date.now()
        });
        
        return result;
      }
    };
  }
  
  private recordMetric(label: string, metric: CompressionMetric): void {
    if (!this.metrics.has(label)) {
      this.metrics.set(label, []);
    }
    
    const metrics = this.metrics.get(label)!;
    metrics.push(metric);
    
    // Keep only last 1000 metrics
    if (metrics.length > 1000) {
      metrics.shift();
    }
  }
  
  getMetrics(label: string): CompressionSummary | null {
    const metrics = this.metrics.get(label);
    if (!metrics || metrics.length === 0) {
      return null;
    }
    
    const totalOriginal = metrics.reduce((sum, m) => sum + m.originalSize, 0);
    const totalCompressed = metrics.reduce((sum, m) => sum + m.compressedSize, 0);
    const totalDuration = metrics.reduce((sum, m) => sum + m.duration, 0);
    
    return {
      label,
      operationCount: metrics.length,
      totalOriginalBytes: totalOriginal,
      totalCompressedBytes: totalCompressed,
      totalDurationMs: totalDuration,
      averageDurationMs: totalDuration / metrics.length,
      compressionRatio: totalOriginal / totalCompressed,
      spaceSavingsPercent: ((totalOriginal - totalCompressed) / totalOriginal) * 100
    };
  }
  
  getAllMetrics(): Map<string, CompressionSummary> {
    const summaries = new Map<string, CompressionSummary>();
    
    for (const label of this.metrics.keys()) {
      const summary = this.getMetrics(label);
      if (summary) {
        summaries.set(label, summary);
      }
    }
    
    return summaries;
  }
  
  clearMetrics(label?: string): void {
    if (label) {
      this.metrics.delete(label);
    } else {
      this.metrics.clear();
    }
  }
}

interface CompressionMetric {
  operation: string;
  originalSize: number;
  compressedSize: number;
  duration: number;
  timestamp: number;
}

interface CompressionSummary {
  label: string;
  operationCount: number;
  totalOriginalBytes: number;
  totalCompressedBytes: number;
  totalDurationMs: number;
  averageDurationMs: number;
  compressionRatio: number;
  spaceSavingsPercent: number;
}

docs

data-processing-summary.md

index.md

network-utilities.md

protocol-message-utilities.md

request-management.md

retry-rate-limiting.md

storage-services.md

tree-blob-utilities.md

url-compression.md

tile.json