or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

compatibility-management.mddatastore-operations.mdgarbage-collection.mdhandle-management.mdindex.mdruntime-factories.mdstorage-utilities.mdsummary-management.mdtelemetry-utilities.md
tile.json

storage-utilities.mddocs/

Storage Utilities ❌ Internal API

Utilities for working with object storage, blob handling, and snapshot tree operations. These tools enable efficient data persistence and retrieval patterns, providing abstractions for storage partitioning and path normalization.

Internal API Warning: All APIs in this document are internal to the Fluid Framework and are not exported for public use. These utilities are implementation details that may change without notice. They are documented here for framework contributors and advanced users who need to understand the internal workings.

Internal APIs ❌

The following APIs are not available for public use and are internal implementation details:

Object Storage Partitioning ❌ Internal

Create isolated views of storage that treat a specific path as the root, enabling modular storage management.

Status: Internal implementation detail - not exported

/**
 * Returns a new IChannelStorageService that resolves the given path as root
 */
class ObjectStoragePartition {
  /**
   * @param storage - The underlying storage service
   * @param path - The path to treat as the root for this partition
   */
  constructor(storage: IChannelStorageService, path: string);
  
  /**
   * Read blob contents from the partition
   * @param path - Path relative to the partition root
   * @returns Promise resolving to the blob contents
   */
  readBlob(path: string): Promise<ArrayBufferLike>;
  
  /**
   * Check if a blob exists at the given path in the partition
   * @param path - Path relative to the partition root
   * @returns Promise resolving to true if the blob exists
   */
  contains(path: string): Promise<boolean>;
  
  /**
   * List all blobs at the given path in the partition
   * @param path - Path relative to the partition root
   * @returns Promise resolving to array of blob names
   */
  list(path: string): Promise<string[]>;
}

Path Normalization ❌ Internal

Utilities for normalizing and working with storage paths, ensuring consistent path handling across the framework.

Status: Internal implementation detail - not exported

/**
 * Normalizes a storage path by removing leading and trailing slashes and splitting into parts
 * @param path - The storage path to normalize (e.g. "/foo/bar/")
 * @returns Array of path segments (e.g. ["foo", "bar"])
 */
function getNormalizedObjectStoragePathParts(path: string): string[];

Tree Navigation ❌ Internal

Utilities for navigating and listing contents within snapshot trees, supporting hierarchical storage access.

Status: Internal implementation detail - not exported

/**
 * Lists all blobs at the specified path in the given tree
 * @param inputTree - The tree to search within
 * @param path - The path to search at (e.g. "foo/bar")
 * @returns Promise that resolves to an array of blob names at that path
 * @throws Error if the path does not exist in the tree
 */
function listBlobsAtTreePath(
  inputTree: ITree | undefined,
  path: string
): Promise<string[]>;

Snapshot Loading Utilities ❌ Internal

Utilities for determining when snapshots need to be fetched for proper loading of storage groups.

Status: Internal implementation detail - not exported

/**
 * Utility function to check if any blobs under a snapshot tree are missing
 * @param snapshotTree - Snapshot tree to be evaluated for missing blobs
 * @param blobContents - Blob contents of the snapshot
 * @returns True if snapshot fetch is required, false otherwise
 */
function isSnapshotFetchRequiredForLoadingGroupId(
  snapshotTree: ISnapshotTree,
  blobContents: Map<string, ArrayBuffer>
): boolean;

Migration Guidance

Since all APIs in this module are internal and not exported, there are no direct replacements available in the public API. If you need similar functionality:

  1. Storage Partitioning: Use the public container and data store APIs for organizing data
  2. Path Handling: Implement your own path normalization utilities
  3. Tree Navigation: Use the public snapshot APIs from @fluidframework/core-interfaces
  4. Snapshot Loading: Use the standard container loading and snapshot APIs

Example Usage (Internal Only - Not Available Publicly):

// ❌ These imports will NOT work - APIs are internal
// import { 
//   ObjectStoragePartition,
//   getNormalizedObjectStoragePathParts,
//   listBlobsAtTreePath,
//   isSnapshotFetchRequiredForLoadingGroupId
// } from "@fluidframework/runtime-utils";

// Storage partitioning
const rootStorage = getContainerStorage();
const dataStorePartition = new ObjectStoragePartition(
  rootStorage, 
  "datastores/my-component"
);

// All operations now work relative to "datastores/my-component"
const configBlob = await dataStorePartition.readBlob("config.json");
const hasCache = await dataStorePartition.contains("cache/data.bin");
const allFiles = await dataStorePartition.list("");

// Path normalization
const pathParts = getNormalizedObjectStoragePathParts("/foo/bar/baz/");
console.log(pathParts); // ["foo", "bar", "baz"]

const emptyParts = getNormalizedObjectStoragePathParts("///");
console.log(emptyParts); // []

// Tree navigation
const tree = await getSnapshotTree();
try {
  const blobsInPath = await listBlobsAtTreePath(tree, "settings");
  console.log("Configuration blobs:", blobsInPath);
} catch (error) {
  console.log("Settings path does not exist");
}

// Snapshot loading check
const snapshotTree = await getLatestSnapshot();
const blobContents = new Map<string, ArrayBuffer>();
await loadBlobContents(blobContents);

if (isSnapshotFetchRequiredForLoadingGroupId(snapshotTree, blobContents)) {
  console.log("Need to fetch additional snapshot data");
  await fetchMissingBlobs(snapshotTree, blobContents);
}

Advanced Storage Patterns

// Hierarchical storage access
class ComponentStorage {
  private partition: ObjectStoragePartition;
  
  constructor(rootStorage: IChannelStorageService, componentId: string) {
    this.partition = new ObjectStoragePartition(
      rootStorage, 
      `components/${componentId}`
    );
  }
  
  async loadConfiguration(): Promise<any> {
    if (await this.partition.contains("config.json")) {
      const configData = await this.partition.readBlob("config.json");
      return JSON.parse(new TextDecoder().decode(configData));
    }
    return {};
  }
  
  async saveData(key: string, data: any): Promise<void> {
    const jsonData = JSON.stringify(data);
    const blob = new TextEncoder().encode(jsonData);
    // Note: This example assumes a writable storage interface
    // The actual ObjectStoragePartition is read-only
  }
  
  async listAllData(): Promise<string[]> {
    return this.partition.list("data");
  }
}

// Path manipulation utilities
function joinStoragePaths(...parts: string[]): string {
  return parts
    .flatMap(part => getNormalizedObjectStoragePathParts(part))
    .join("/");
}

function getParentPath(path: string): string {
  const parts = getNormalizedObjectStoragePathParts(path);
  return parts.slice(0, -1).join("/");
}

// Tree traversal example
async function findAllBlobsInTree(
  tree: ITree | undefined, 
  basePath: string = ""
): Promise<string[]> {
  if (!tree) return [];
  
  const allBlobs: string[] = [];
  
  try {
    const blobsAtPath = await listBlobsAtTreePath(tree, basePath);
    allBlobs.push(...blobsAtPath.map(name => 
      basePath ? `${basePath}/${name}` : name
    ));
  } catch {
    // Path doesn't exist, continue
  }
  
  // Recursively search subdirectories
  // Note: This would require additional tree navigation utilities
  // that aren't part of the current API
  
  return allBlobs;
}